Compare commits

..

186 Commits

Author SHA1 Message Date
d471e3a23b Bump version to 3.33.4
Update NEWS.
2019-07-20 17:47:10 +02:00
ce1bee727a extensionSystem: Allow disabling session mode extensions
Trying to disable an extension that is enabled by the session mode
currently has no effect, which is clearly confusing. We could update
the various extension UIs to reflect that via sensitivity, but being
unable to configure extensions based on which session the user picked
at login isn't obvious either.

So instead, add a 'disabled-extensions' gsettings key to list extensions
that should not be enabled which takes precedence over 'enabled-extensions'
and can be used to disable session mode extensions.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
43cb3754d9 extensionSystem: Store extensions in a Map
After making the extensions map private to the ExtensionManager, we can
switch it to a proper hash table which is more appropriate.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
1d6ddf060b extensionSystem: Move extension loading into ExtensionManager
Now that extension loading and the extensions map are no longer shared
between the gnome-shell and gnome-shell-extension-prefs processes, we
can move both into the ExtensionManager which makes much more sense
conceptually.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
9928125e7d extensionPrefs: Switch to D-Bus API to get extension live state
By direclty using the underlying GSetting, whether or not an extension
appears as enabled or disabled currently depends only on whether it is
included in the 'enabled-extensions' list or not.

However this doesn't necessarily reflect the real extension state, as an
extension may be in error state, or enabled via the session mode.

Switch to the extensions D-Bus API to ensure that the list of extensions
and each extension's state correctly reflects the state in gnome-shell.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
1c63893c4b extensionPrefs: Override getCurrentExtension() for extensions
Extensions are used to calling the getCurrentExtension() utility function,
both from the extension itself and from its preferences. For the latter,
that relies on the extensions map in ExtensionUtils being populated from
the separated extension-prefs process just like from gnome-shell.

This won't be the case anymore when we switch to the extensions D-Bus API,
but as we know which extension we are showing the prefs dialog for, we
can patch in a simple replacement that gives extensions the expected API.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
a7ec7583aa extensionPrefs: Attach extension object to each row
Each row represents an extension, so it makes sense to associate the
rows with the actual extensions instead of linking rows and extensions
by looking up the UUID in the external extensions map in ExtensionUtils.

This will also make it much easier to stop using the shared extension
loading / map in favor of the extension D-Bus API.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
4a3476266f extensionSystem: Add canChange property to extensions
Whether or not an extension can be enabled/disabled depends on various
factors: Whether the extension is in error state, whether user extensions
are disabled and whether the underlying GSettings keys are writable.

This is complex enough to share the logic, so add it to the extension
properties that are exposed over D-Bus.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
32e0b895a4 shellDBus: Add new 'ExtensionStateChanged' signal
The existing 'ExtensionStatusChanged' signal has a fixed set of parameters,
which means we cannot add additional state without an API break.  Deprecate
it in favor of a new 'ExtensionStateChanged' signal which addresses this
issue by taking the full serialized extension as parameter.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
58806359ee extensionUtils: Add functions to (de)serialize extensions
Serializing an extension for sending over D-Bus is currently done by the
appropriate D-Bus method implementations. Split out the code as utility
function and add a corresponding deserialization function, which we will
soon use when consuming the D-Bus extension API from the extension-prefs
tool.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
4589da957b extensionSystem: Add methods to enable/disable extensions
Extensions are currently enabled or disabled by directly changing the
list in the 'enabled-extensions' GSettings key. As we will soon add
an overriding 'disabled-extensions' key as well, it makes sense to
offer explicit API for enabling/disabling to avoid duplicating the
logic.

For the corresponding D-Bus API, the methods were even mentioned in
the GSettings schema, albeit unimplemented until now.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
6a4c55b852 extensionSystem: Make methods to call extension functions private
While public methods to enable/disable extensions make sense for an
extension manager, the existing ones are only used internally. Make
them private and rename them, so that we can re-use the current
names for more useful public methods.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
ea17740719 extensionSystem: Turn into a class
The extension system started out as a set of simple functions, but
gained more state later, and even some hacks to emit signals without
having an object to emit them on.

There is no good reason for that weirdness, so rather than imitating an
object, wrap the existing system into a real ExtensionManager object.

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
d82810240f extensionUtils: Move ExtensionState definition here
It makes sense to keep extension-related enums in the same module instead
of spreading them between ExtensionSystem and ExtensionUtils.

More importantly, this will make the type available to the extensions-prefs
tool (which runs in a different process and therefore only has access to
a limited set of modules).

https://bugzilla.gnome.org/show_bug.cgi?id=789852
2019-07-20 14:17:35 +00:00
2768b73015 build: Clean out unused version requirements
We haven't linked to those libraries in years ...
2019-07-20 12:39:16 +02:00
f9a7718dda background: Adjust to gnome-desktop API break
gnome-desktop broke API in commit ca5d61cf24, as it didn't *add* a property
as incorrectly stated in the commit message, but *replaced* an existing one.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1457
2019-07-20 12:26:28 +02:00
d9d9778a98 main: Avoid missing braces warnings when compiling with clang
Since -Werror=missing-braces is used, having missing braces warnings
aren't allowed. However, the first member of struct sigaction is a union
whose first member is a pointer, causing clang to produce warnings when
it is initialized to { 0 }.

Instead of initializing to a zero value, we can specify values of
members directly in the initializer to avoid warnings.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/633
2019-07-20 16:45:49 +08:00
bd5162105e power: Make sure we fall back to the correct icon
Commit bd18313d12 changed to a new naming scheme for battery icons,
and used to old icon names as fallback-icon-name for compatibility
with older/other icon themes.

However that fallback code isn't working correctly, as GThemedIcon's
default fallbacks will transform a name of `battery-level-90-symbolic`
to a list of names:
 - `battery-level-90-symbolic`
 - `battery-level-symbolic`
 - `battery-symbolic`

The last one frequently exists, so instead of the intended fallback,
we end up with a generic battery icon.

Address this by specifying the icon as GIcon instead of an icon-name,
where we have more control over how the icon is resolved.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1442
2019-07-19 19:11:37 +00:00
208c5e9562 shell: Don't use g_memmove()
Glib stopped providing any fallback implementations on systems without
memmove() all the way back in 2013. Since then, the symbol is a simple
macro around memmove(); use that function directly now that glib added
a deprecation warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/632
2019-07-19 17:43:56 +00:00
305e63750e workspacesView: Support horizontal layout
Just as we did for the workspace switcher popup, support workspaces
being laid out in a single row in the window picker.

Note that this takes care of the various workspace switch actions in
the overview (scrolling, panning, touch(pad) gestures) as well as the
switch animation, but not of the overview's workspace switcher component.

There are currently no plans to support other layouts there, as the
component is inherently vertical (in fact, it was the whole reason for
switching the layout in the first place).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575
2019-07-19 11:01:24 +02:00
ab0f74aa15 workspaceSwitcherPopup: Support horizontal layout
While mutter supports a variety of different grid layouts (n columns/rows,
growing vertically or horizontally from any of the four corners), we
hardcode a fixed vertical layout of a single column.

Now that mutter exposes the actual layout to us, add support for a more
traditional horizontal layout as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/575
2019-07-19 11:01:24 +02:00
43443d08ae theme: app icon helper tweaks
Shell cannot composite multiple shadows, simplify to only use one.

https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/168
2019-07-18 05:17:56 +02:00
b82b553b9e extensionPrefs: Inherit from Gtk.Application
Extension preferences Application class is just a container for a GtkApplication
so instead of using composition we can inherit from the base GObject class.

Also replace signal connections with vfunc's.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/631
2019-07-17 12:59:08 +00:00
08464eadff theme: make overview thumbnails rounder
- match gtk Adwaita

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1449
2019-07-16 05:29:23 +02:00
49e56776e8 theme: unbreak acrive states for icon tiles
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1446
2019-07-16 00:16:32 +02:00
043667dde5 theme: Provide icon helper classes
- to help present icons on light backgrounds, the new fullcolor
  icons need some help. Mimic gtk styles

Needed for https://gitlab.gnome.org/GNOME/gnome-shell-extensions/issues/168
2019-07-16 00:07:51 +02:00
f583a7c6d8 Update Karbi translation 2019-07-16 02:39:07 +00:00
2d908e80fc search: Remove wrong additional argument for _createResultDisplay
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/110
2019-07-15 23:00:34 +00:00
8f0e9abe47 iconGrid: Make sure the style is updated before computing the layout
In some cases the style-changed signal hasn't been emitted when
_computeLayout() is called, resulting in the use of the default spacing
and item size values for the calculations.

One case where this happens is when starting a search. Right after the
initialization of GridSearchResults, _computeLayout() is called from
_getMaxDisplayedResults() and the style-changed signal hasn't been
emitted yet. The computed layout will be wrong and the maximum
number of results will also be wrong.

To prevent this from happening, make sure the style has been updated
before doing the calculations in _computeLayout().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/110
2019-07-15 23:00:34 +00:00
1a27ff6130 search: Fix calculation of max number of displayed results for grid
The calculation of how many results can be shown in GridSearchResults is
broken: The width of the parent container (resultsView.actor) we're
using as the maximum width right now is the width of the scrollView of
SearchResults (which always expands to the whole screen size). This
width will only be correct if the scrollView (ie. the whole screen) is
smaller than the max width of searchResultsContent, which only is the
case for screens smaller than 1000px.

To fix the calculation, use the width of our own actor and don't get it
using clutter_actor_get_width(), but using the last allocation of the
actor. This way we don't get the preferred width if the actor is not
allocated at this point (it's hidden by _ensureProviderDisplay() when
starting a new search).

Then, when the allocation of the actor changes, rebuild the grid search
results by calling updateSearch() with the old arguments to ensure the
number of visible results is correct. The fact that we're only listening
for allocation changes here is the reason why we never want to use the
preferred width of the actor inside _getMaxDisplayedResults(): While
the actor is hidden clutter_actor_get_width() would return the preferred
width, which we'd then use the as the maximum width. But if the actor
had a correct allocation before, no notify::allocation signal will be
emitted when the actor is shown again because the allocation is still
the same, and we'll end up using the preferred width as maximium width
forever.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/110
2019-07-15 23:00:34 +00:00
3f2cffc2e6 theme: Don't apply overlap-preventing padding to search results
Unlike the app grid, we show the search results while the dash is hidden
and with a small scrollbar instead of page indicator dots. This
means there's nothing the search results might horizontally overlap
with and the padding here is unneccessary.

The spacing between the search results and the screen edges is still
sufficient because of the paddings applied to searchResultsContent.

On very small screens (< 1000px), this allows the search results to
utilize a lot more of the horizontal screen space.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/110
2019-07-15 23:00:34 +00:00
a78527050a search: Remove unnecessary containers
The functionality the searchResultsBin container provides can easily be
moved into a subclass of St.BoxLayout, no need for an additional StBin.
The "searchResultsBin" css class isn't used in the stylesheets either.

Same with the scrollChild container.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/110
2019-07-15 23:00:34 +00:00
a823a213ba Update Karbi translation 2019-07-15 10:54:50 +00:00
2c8d380e67 shellDBus: Rename ShowMonitorLabels2 to ShowMonitorLabels
The original ShowMonitorLabels has been removed so we can change things
back to use ShowMonitorLabels again.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/491
2019-07-15 11:18:29 +02:00
3996309f8a Add Karbi translation 2019-07-14 04:02:53 +00:00
bd18313d12 power: Use more fine-grained battery levels
Adwaita-icon-theme added new battery icons which represent battery levels
in 10% steps[0]. Use these if they are available, otherwise fall back to
the existing icon names for compatibility with older icon themes.

[0] https://gitlab.gnome.org/GNOME/adwaita-icon-theme/issues/6

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/561
2019-07-12 23:24:35 +02:00
2ff7a78b56 calendar: Simplify code a bit
Just make the error case the same as the no-appointments one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
c765082f72 calendar: Avoid a warning
We will always get a results array from gjs' proxy wrapper, but it
will be empty in the error case; that is, `results` is always defined,
but `results[0]` may not be.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
7d2c5c1ac9 dialog: Use Object.assign() for default property value
Either Params.parse() or Object.assign() are more concise for providing
default values in object literals (sadly default parameters won't work
here).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
404bc34089 cleanup: Use default parameters where appropriate
Since ES6 it is possible to set an explicit default value for optional
parameters (overriding the implicit value of 'undefined'). Use them
for a nice small cleanup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
16ca7a21a7 panel: Relax check for existing signal handler
Object.prototype.hasOwnProperty() is more precise than checking for
falsiness, for instance the following is true:

  { foo: undefined }.hasOwnProperty('foo');

However when checking for a handler ID, a more relaxed check is more
appropriate, as particularly 0 is not a valid handler ID.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
1b31fd5afe cleanup: Don't call method via a parent's prototype
We cannot disconnect a signal handler via the usual disconnect() as
nm_device_disconnect() shadows the GObject method, but we can use
g_signal_handler_disconnect().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/626
2019-07-12 18:54:49 +00:00
e0457b6dc4 lint: Add "legacy" configuration
Regarding coding style, gjs is moving in a direction that departs quite
significantly from the established style, in particular when indenting
multi-line array/object literals or method arguments:

Currently we are keeping those elements aligned, while the gjs rules now
expect them to use the regular 4-space indentation.

There are certainly good arguments that can be made for that move - it's
much less prone to leading to overly-long lines, and matches popluar JS
styles elsewhere. But switching coding style implies large diffs which
interfere with git-blame and friends, so in order to allow for a more
gradual change, add a separate set of "legacy" rules that match more
closely the style we would expect up to now.

It also disables the rules for quotes and template strings - the former
because we cannot match the current style to use double-quotes for
translatable strings and single-quotes otherwise, the latter because
template strings are still relatively new, so we haven't adopted them
yet.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
42b77e7ba5 lint: Allow multiple spaces before key values
This is useful for imitating namespaced flags/enums:

```
const FooFlags = {
    NONE:    0,
    SMEAGLY: 1 << 0,
    SMOGLEY: 1 << 1,
    MUGGLY:  1 << 2
};
```

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
f6bed08993 lint: Enforce camelCase
All variables should be in camelCase, so configure the corresponding
rule to enforce this. Exempt properties for now, to accommodate the
existing practice of using C-style underscore names for construct
properties of introspected objects.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
5f77cdb0b9 lint: Enforce arrow notation
We replaced all Lang.bind() calls with arrow functions or the standardized
Function.prototype.bind(), at least for the former eslint has some options
to ensure that the old custom doesn't sneak back in.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
109b8e8f38 lint: Require spaces inside braces in object literals
Prohibiting spaces where the established GNOME style has required
them for a decade would be a harsh change for no good reason.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
4c0bd88a2c lint: Tweak the whitelist of globals
gjs doesn't include any gettext wrappers, and obviously can't know
about the shell's global object, so include those in the list of
globals for all sources in the gnome-shell context.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
3731be9947 lint: Import eslint rules from gjs
gjs started to run eslint during its CI a while ago, so there is an
existing rules set we can use as a starting point for our own setup.

As we will adapt those rules to our code base, we don't want those
changes to make it harder to synchronize the copy with future gjs
changes, so include the rules from a separate file rather than using
the configuration directly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/609
2019-07-12 16:01:07 +00:00
6cc19ee6f0 workspacesView: Work around spurious allocation changes
For some reason, people are still seeing those after commit d5ebd8c8.
While this is something we really should figure out, we can work around
the issue by keeping the view actors hidden until the update is complete.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1065
2019-07-12 16:48:03 +02:00
1570f838f3 cleanup: Remove bogus file
This was accidentally added in commit 14d7897a9.
2019-07-12 10:36:37 +00:00
74feb110b5 layout: Fix off-by-one indent
This sneaked into commit dbb71f0d :-(
2019-07-11 03:02:20 +02:00
6ba03ac2a6 params: Don't use Lang module
To copy the passed in default parameters, we can just as well use
another Object.assign() call.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/616
2019-07-10 22:09:09 +00:00
55c717c2dc appDisplay: Fix logic error
Commit f6b4b96737 accidentally swapped the conditions here from
!includes() to includes().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/621
2019-07-10 21:50:17 +00:00
355b5eebec workspace: Set offscreen redirect on window previews
Window previews are sometimes shown translucent, for example during
drags or animations. They can also have attached dialogs, in which
case the opacity should affect the combination of all windows instead
of being applied to each window individually, blended together, so
make sure they are redirected as a whole when necessary.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/774
2019-07-10 21:41:58 +00:00
51938c398a workspace: Let WindowClone inherit from StWidget
Using inheritance over delegation will give us more control over
the actor drawing.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/774
2019-07-10 21:41:58 +00:00
dbb71f0dfc layout: Make the hot corner optional
Whether people love or hate the hot corner depends in large extents
on hardware sensitivity and habits, which is hard to get right
universally. So bite the bullet and support an option to enable or
disable hot corners ...

https://bugzilla.gnome.org/show_bug.cgi?id=688320
2019-07-10 17:29:24 +02:00
1cac7b2218 windowManager: Remove unused property
The last commit removed the only code that set _blockAnimations,
so stop reading it as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/620
2019-07-09 14:46:36 +02:00
ff9bb5399b windowManager: Use new reorder_workspace() API
With the new Mutter API, inserting a workspace at a particular position
becomes as easy as creating the workspace and moving it to the desired
index.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/620
2019-07-09 14:41:35 +02:00
68e45eb051 workspaceThumbnails: Handle reordering of workspaces
MetaWorkspaceManager gained the ability to reorder workspaces, so make
sure to pick up the new order when that happens.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/620
2019-07-09 14:41:35 +02:00
d0da96ad29 workspacesView: Handle reordering of workspaces
MetaWorkspaceManager gained the ability to reorder workspaces, so make
sure to pick up the new order when that happens.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/620
2019-07-09 14:41:35 +02:00
55b036170b shell-recorder: Restore cursor recording
Due to changes introduced in 5357e0a1 cursor recording interaction with
magnifier was reversed. This fix restores original correct behavior
Related issue: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1208
2019-07-08 21:08:51 +00:00
5473637736 cleanup: Fix style nits in last commit
Missing space after catch and wrong double quotes.
2019-07-08 20:15:15 +02:00
bb6d9734e4 endSessionDialog: Check for PackageKit before considering updates/upgrades
GNOME Shell is spitting out some errors in the journal due to its attempts
to speak to PackageKit, which is not present on Endless OS, so let's add
some runtime checks to make sure that PackageKit is actually available
before assuming so and using its proxy to decide which kind of UI to
show to the user when ending the session.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/369
2019-07-08 13:57:23 +02:00
53be76c9e2 shellDBus: Update ::accelerator-activated handler arguments
Mutter now passes a ClutterInputDevice. And use this to pass the
device ID (as we used to do) and the event node (so we can transition
to something that works on x11/wayland)

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/618
2019-07-08 11:53:42 +02:00
be40de5a9b st: Consider non-background properties for ::style-changed
st_theme_node_paint_equal() was originally added to preserve paint state
when a style change didn't affect any of StWidget's cached background
resources.
That's why using it for filtering out unneeded style changes as in commit
f662864a misses any non-background related properties that are relevant
for subclasses. Add additional tests to make sure we keep emitting the
signal in those cases.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1212
2019-07-07 21:01:33 +00:00
7359e431d3 st: Add st_icon_colors_equal()
This is a small convenience wrapper around clutter_color_equal()
for the different color components, which also handles the case
where one (or both) of the icon colors are %NULL.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1212
2019-07-07 21:01:33 +00:00
8a5de327bb params: Fix regression
The first parameter to Object.assign() is the same target object that
will be returned. That is, since commit 46874eed0 Params.parse() modifies
the @defaults object. Usually we pass that parameter as an object literal
and this isn't an issue, but the change breaks spectacularly in the few
cases where we use a re-usable variable.

Restore the previous behavior by copying the object first.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/615
2019-07-05 18:28:26 +02:00
1778adae0d tests: Add Params.parse() unit tests
Commit 46874eed0 accidentally changed the behavior of the function in
an incompatible way. Before addressing the actual issue, add a reproducer
to the unit tests to hopefully prevent future breakage.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/615
2019-07-05 18:28:26 +02:00
0d035a4e53 cleanup: Prefer template strings
Template strings are much nicer than string concatenation, so use
them where possible; this excludes translatable strings and any
strings containing '/' (until we can depend on gettext >= 0.20[0]).

[0] https://savannah.gnu.org/bugs/?50920

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/612
2019-07-05 11:32:31 +00:00
46874eed05 params: Simplify code
Standard javascript now has Object.assign() which is very similar to
Params.parse(), except that the latter by default disallows "extra"
parameters. We can still leverage the standard API by simply
implementing the error check, and then call out to Object.assign()
for the actual parameter merging.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/612
2019-07-05 11:32:31 +00:00
e95f3febd6 ibusManager: Use Map to store engines
This is a clear case of key->value mapping, so using the corresponding
data type makes sense.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/612
2019-07-05 11:32:31 +00:00
0bdd1b6fc4 st/button: Ungrab device before calling st_button_release
Since priv->device gets set to NULL inside st_button_release, ungrab the
input device before calling st_button_release and avoid
clutter_input_device_ungrab failing with a critical error.

This fixes a regression introduced with
d5a1a888d9

While at it, also remove the superfluous line resetting priv->device to
NULL and move the check for priv->grabbed into an elseif block since
there should be no case where StButton has both grabs at the same time.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/614
2019-07-04 18:25:15 +02:00
8a22092632 shell: Drop XDND initialization code
Let mutter take over this, and drop this piece of backend-specific
code.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/611
2019-07-03 16:37:15 +02:00
915415d919 OSK variables and key rounding
- generate the OSK key colors from variables in _colors.scss without changing the design
- add hover and active colors for all key, not only letter keys
- use $button_radius for the OSK keys, buttons and entries (no value change for the latter)

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/610
2019-07-02 21:10:33 +02:00
14d7897a93 style: Stop using braces for single-line arrow functions
Braces are optional for single-line arrow functions, but there's a
subtle difference:
Without braces, the expression is implicitly used as return value; with
braces, the function returns nothing unless there's an explicit return.

We currently reflect that in our style by only omitting braces when the
function is expected to have a return value, but that's not very obvious,
not an important differentiation to make, and not easy to express in an
automatic rule.

So just omit braces consistently as mandated by gjs' coding style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
1398aa6562 style: Fix indentation errors
While we have some style inconsistencies - mostly regarding split lines,
i.e. aligning to the first arguments vs. a four-space indent - there are
a couple of places where the spacing is simply wrong. Fix those.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
8fcd6c7153 cleanup: Use arrow functions for tweener callbacks
While it is legal to use method syntax for the function properties
here, arrow notation is less unexpected and allows us to drop the
separate scope properties.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
6ed5bc2f6c cleanup: Use consistent switch indentation
We are currently inconsistent on whether case labels share the same
indentation level as the corresponding switch statement or not. gjs
goes with the default of no additional indentation, so go along with
that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
5ec4c2e43e cleanup: Use spaces for indentation
Our indentation style has always mandated spaces, but over the years
some tabs sneaked in. Fix up those places.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
6f8dd065a4 cleanup: Use consistent style for GObject property definitions
Go with the style preferred by gjs.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
02db21fc55 systemActions: Reindent action map
Starting an object literal with a comment throws off eslint's rules
for brace style (newline between brace and properties for both opening
and closing brace or neither) as well as indentation (fixed four-space
indent or align with the previous argument).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
8c28f9a77d dwellClick: Reindent modes map
Using multiple spaces after property names in order to align the
values isn't something we do elsewhere.

Instead, align the values by using a fixed 4-space indent as preferred
by gjs nowadays.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
95b80eec01 extensionPrefs: Avoid awkward indentation in string literal
The current code is carefully avoiding an overly wide line length as
well as adding literal new lines to the string due to indentation. It's
clever and barely legible.

Instead, use one string per line similar to how they appear in the actual
output, and join them together when setting the clipboard text.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/608
2019-07-02 12:17:46 +00:00
02c76695e5 tests: Stop using global grabs
Global grabs are being removed from Clutter in favour of input device
grabs.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/495
2019-07-02 01:18:15 +00:00
d5a1a888d9 st: Replace global grabs with input device grabs
Global grabs are being removed from Clutter in favour of input device
grabs, so only grab the input device instead and replace priv->grabbed
with checks for priv->grab_device.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/495
2019-07-02 01:18:15 +00:00
6c33aff6d1 lookingGlass: Replace global grabs with input device grabs
Global grabs are being removed from Clutter in favour of input device
grabs.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/495
2019-07-02 01:18:15 +00:00
61f86cbc54 keyboard: Remove unused keyboard gsetting schema
Since commit 7fd8fa34, the schema is no longer used.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/604
2019-07-02 02:56:48 +02:00
4c5206954a style: Use camelCase for variable names
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
8fda3116f0 style: Fix brace style
Opening braces should be on the same line as the associated statement,
and only be omitted if both surrounding blocks are one-liners.

Partially spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
7ac35c644e style: Fix stray/missing spaces
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
29b04fcbf2 style: Fix stray/missing semi-colons
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
55235c2552 style: Avoid trailing commas in array destructuring
When destructuring multiple return values, we often use trailing commas
to indicate that there are additional elements that we are ignoring.

There isn't anything inherently wrong with that, but it's a style that's
too confusing for eslint - on the one hand we require a space after a
comma, on the other hand we require no space before closing brackets.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
f250643385 style: Use space after catch
We are currently inconsistent with whether or not to put a space
after catch clauses. While the predominant style is to omit it,
that's inconsistent with the style we use for any other statement.
There's not really a good reason to stick with it, so switch to
the style gjs/eslint default to.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
d008c6c5c5 cleanup: Avoid variable declarations in case clauses
While allowed by the syntax, they are problematic because the
variable is in the scope of the switch() statement, but only
valid if a particular case clause is reached.

Add braces to limit the variables' scope to the corresponding
case clause to avoid that problem.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
e2e02c9a2f cleanup: Avoid implicit coercion
Converting a variable to a particular type can be done explicitly (with
functions like Number() or toString()) or implicitly by relying on type
coercion (like concatenating a variable to the empty string to force
a string, or multiplying it with 1 to force a number).

As those tend to be less readable and clear, they are best avoided. So
replace the cases of string coercion we use with template strings, and
clarify the places that can be confused with number coercion.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:11 +02:00
e56d7f5021 cleanup: Remove unused variables
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:10 +02:00
e7d44bb349 cleanup: Remove unneeded escapes in regex
. and ) lose their special meaning in character sets, so they don't
need escaping. The same applies to - when it isn't part of a range.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:10 +02:00
321730fcb9 cleanup: Use rest operator to handle overly long argument lists
The existing indentation is bonkers, but there's no good replacement
with that many arguments. So switch to using the rest operator and
array destructuring as an alternative.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:10 +02:00
fe83cd91bb cleanup: Use rest parameters instead of arguments
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:10 +02:00
0b08ee54bb cleanup: Clean up unused imports
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/607
2019-07-01 23:44:10 +02:00
f6b4b96737 cleanup: Use Array.includes() to check for element existence
We can use that newer method where we don't care about the actual position
of an element inside the array.

(Array.includes() and Array.indexOf() do behave differently in edge cases,
for example in the handling of NaN, but those don't matter to us)

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/152
2019-07-01 21:28:52 +00:00
b87455c089 keyboard: Remove unnecessary boolean cast
In contexts where a statement (like if or while) expects a condition,
any expression will be implicitly cast to boolean already without
C-isms like double negation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
2c1a81f448 runDialog: Don't return from finally block
Control flow statements like return, break or continue are considered
unsafe in finally blocks, as they take precendence over any control
flow statement in the try and catch blocks, which may be unexpected.

This isn't the case here as the statement in the finally block is the
only one, but we can just as well avoid the finally block altogether
and use a regular return statement.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
b3736f45e6 popupMenu: Use regular method style
We don't define methods on a single line anywhere else, so don't do
that here either for consistency.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
3c382c4bbe popupMenu: Use consistent registerClass() style
We don't add a line break between parameters and class elsewhere,
so be consistent with that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
5f3bad9c94 locatePointer: Use constant for GSettings key
The constant is defined, so use it.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
6970f43e66 ripples: Remove unreachable return statements
Throwing an exception stops execution of the current function,
so the following return statements are both unnecessary and
unreachable.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
9476aa598a telepathyClient: Don't redeclare N_()
It is already defined globally via environment.js.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
69725e5d41 locatePointer: Capitalize class name
... according to our coding style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
42dabef8c7 loginDialog: Return consistently from arrow function
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
e10a768ddb shellMountOperation: Remove unused functions
Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
a8f0787c91 batch: Add missing import
Commit 88697add1b missed adding the necessary import.

Spotted by eslint.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/606
2019-07-01 21:09:49 +00:00
074129682b altTab: Remove get_preferred_width override of AppIcon
This vfunc override has been introduced to ensure app icons are always
squared, but since the container of the AppIcon gets a square allocation
anyway if the 'square' property of the SwitcherButton is set, there's
no need to return a special width here.

Without the override we can also stop setting the size of the iconBin
manually. And since shell_app_create_icon_texture() uses logical pixels
but clutter_actor_set_size() uses screen pixels, that means we now no
longer set the size of the icon back to the unscaled value after it was
already correct.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1325
2019-07-01 20:46:26 +02:00
c67460a1e3 altTab: Fix a wrong variable name
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/587
2019-07-01 20:05:16 +02:00
eab320dab5 altTab: Ensure style of this._list before calculating icon sizes
We're calculating icon sizes for the alt tab switcher early and at a
point where the style attributes of this._list are not loaded yet. To
make sure the value of this._list.spacing is correct, call
ensure_style() on this._list before accessing the spacing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/587
2019-07-01 20:05:16 +02:00
04c7cb6fbe Do use padding 0 for week and day numbers 2019-07-01 08:53:46 +02:00
d4582491f5 system: Drop custom styling of user submenu icon
The default style we get from .popup-menu-icon actually works better,
as it ensures consistency with all the other submenu icons used in
the aggregate menu.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/591
2019-06-29 20:01:52 +00:00
0641b1e279 animation: fix unintentional loop while polkit dialog is active
The polkit password dialog has a spinner that gets displayed
while the users password is being verified.

Unfortunately, the spinner stop method unintentionally calls
back into itself after the stop fade out animation is complete.
The stop method is called at startup, so the looping begins as
soon as the dialog is visible and continues until the dialog is
dismissed.

This commit fixes the loop by having the stop method cease
calling itself, and instead having it call the stop method on the
superclass.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/602
2019-06-27 14:54:36 -04:00
ae0450b68e Revert "animation: fix unintentional loop while polkit dialog is active"
This reverts commit cb0a5de83b.
2019-06-27 14:47:13 -04:00
cb0a5de83b animation: fix unintentional loop while polkit dialog is active
The polkit password dialog has a spinner that gets displayed
while the users password is being verified.

Unfortunately, the spinner stop method unintentionally calls
back into itself after the stop fade out animation is complete.
The stop method is called at startup, so the looping begins as
soon as the dialog is visible and continues until the dialog is
dismissed.

This commit fixes the loop by having the stop method cease
calling itself, and instead having it call the stop method on the
superclass.
2019-06-27 14:27:34 -04:00
2f5086efaf extensionDownloader: Use common message dialog layout
While the confirmation dialog for extension installation is simpler
than - say - authentication dialogs, it still makes sense to re-use
the common content layout instead of duplicating it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/600
2019-06-26 20:49:46 +02:00
68e580e394 dialog: Use GObject.set() over Object.assign()
gjs has provided that as a more idiomatic replacement for a while.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/600
2019-06-26 20:49:46 +02:00
b143869d5d main: Fix some typos and style inconsistencies in comments
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/599
2019-06-26 16:39:36 +00:00
6a477be874 windowManager: Use own variables for each gesture
Using one variable to initialize all gestures will update the address of
the "gesture" pointer with every newly initialized object. This means
that event handlers which also use the "gesture" pointer like the
'keyboard-visible-changed' handler will update a different gesture as
soon as the pointer is changed.

This lead to a bug where the handler of 'keyboard-visible-changed'
wrongly nabled the unfullscreen gesture. Fix that by assigning each
gesture its own variable.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/598
2019-06-26 18:18:28 +02:00
03bb8cdcbd theme: darken sliders to match gtk
- match gtk a bit more closely, but avoid the gradients (change will
  happen on gtk side for this one).
2019-06-26 12:34:42 +02:00
8864816b94 Bump version to 3.33.3
Update NEWS.
2019-06-24 19:19:04 +02:00
751cd2f1c1 main: setup GJS profiler when GJS_TRACE_FD is set
This is the same environment variable that will be used in GJS to auto-
connect Sysprof to the GJS profiler when the gjs binary is used.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/573
2019-06-24 15:05:46 +00:00
6f6b6fb9d6 Merge branch 'wip/jimmac/sync-with-adwaita' 2019-06-24 15:39:26 +02:00
fe346b89f0 Update Catalan translation 2019-06-23 09:48:21 +02:00
0744c6af2e Update Croatian translation 2019-06-21 23:56:14 +00:00
2e070ab834 panel: Center-align menu arrows
Center alignment looks more balanced and makes it more likely that
the menu opens below the pointer position.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1351
2019-06-21 21:09:56 +00:00
00f9b7bf69 layout: Use addChrome instead of addTopChrome for screenShieldGroup
Make sure the panel is visible above the login and screen shield actors
by adding the screenShieldGroup to the uiGroup underneath the panelBox.

This fixes a regression introduced with 2bd80579ed

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/571
2019-06-21 20:57:23 +00:00
94ba52af0c network: don't assume NMActiveConnection has a device
In practice this has been seen to fail:

    JS ERROR: TypeError: active.get_devices(...)[0] is undefined
    ensureActiveConnectionProps@resource:///org/gnome/shell/ui/status/network.js:73:22
    _getMainConnection@resource:///org/gnome/shell/ui/status/network.js:1791:13
    _syncMainConnection@resource:///org/gnome/shell/ui/status/network.js:1809:32

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1406
2019-06-21 11:26:53 +01:00
44e1a6ce06 Theme: update to sync with gtk Adwaita
- consistent OSD colors
- consistent fg/bg colors
- updated rounded corners
- switches

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/841
2019-06-21 10:44:08 +02:00
ccf646f54a Drop CoglError for GError
From https://gitlab.gnome.org/GNOME/mutter/merge_requests/631

```
CoglError was added at a certain point to remove the hard dependency on
GLib, but since this can't be avoided inside mutter, let's remove this
whole abstraction.
```

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/586
2019-06-20 16:30:40 +02:00
4e84b46c9b keyboard: Add extended keys and language popups to top window group
As per commit 2bd80579ed important actors are added to the top window group
using the layout's addTopChrome method.

This group includes the on-screen keyboard, however its popups were not added
and so they are now shown under the OSK and don't receive any input.

Fix this by adding Language popup and extended keys popup to top chrome.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1396
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/583
2019-06-19 00:30:17 +02:00
b4797956c7 iconGrid: Fix animation glitch
Since commit 520cea9394, the opacity of icon grid children is used
both to skip children outside the current viewport and to hide the
real icons while animating icon clones.

As a result, a grid animation during an animation now ends up showing the
icons that are being animated. Avoid that glitch by leaving children's
opacity alone when there's an ongoing animation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/582
2019-06-18 22:03:34 +00:00
c1c45f95af appDisplay: Set Adjustment value after allocation
AllView's adaptToSize is called as part of viewStack allocation vfunc, and this
makes the adjustment value to be reset while relayouting.

So, fix this by delaying this using the Meta later that we already had for
pageIndicators operations.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1392
2019-06-18 23:22:32 +02:00
ac09e0110a Update Dutch translation 2019-06-18 08:33:32 +00:00
0e37cd2ec9 main, LoginManager: Call GDM's RegisterSession()
So that it can know if we started up properly and use that to (e.g.)
kill its greeter.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/570
2019-06-18 09:21:58 +01:00
76dc77f617 boxpointer: Remove deprecated show/hide methods
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/576
2019-06-17 14:22:42 +02:00
cb4c0d32c0 boxpointer: Trigger a relayout when setting position
Since the repositioning is now done during allocation, we can just queue
a relayout when setting the boxpointer positioning via the source actor.

As per this _relayout() and _updateFlip now needs to be called during allocation
only and with an allocation box set.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/576
2019-06-17 14:22:40 +02:00
3d4ba028c4 boxpointer: Don't trigger a relayout when updating arrow side
Changing the arrow side might need to reposition the boxpointer, however
if this happens during allocation, we don't need to trigger a new relayout since
we'd set the new allocation once _updateFlip's _reposition call is terminated,
otherwise if the position has changed, changing the boxpointer coordinates
will trigger a relayout anyways.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/576
2019-06-17 14:22:19 +02:00
5481c1899f boxpointer: Don't set actor position during allocation
As per commit 044572cb60 boxpointer uses its own coordinates to position itself.
However this would lead to warning when mutter-clutter is compiled with debug
options as we'd might try to set the box coordinates during the allocation
cycle.

So, when calling _reposition during allocation, instead of setting the actor's
coordinates we just pass the allocation box and we adjust its origin, in order
to set it properly in the vfunc.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1382
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/576
2019-06-17 14:22:18 +02:00
2fd120162f boxpointer: Unset the sourceActor on destruction
A boxpointer sourceActor could be destroyed before the boxpointer itself.
In such case, unset the sourceActor reference, connecting to 'destroy' signal.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1295
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/576
2019-06-17 12:39:26 +02:00
523ba5a719 shell: Remove shell_global_structured_log()
It is now unused.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/579
2019-06-15 15:26:17 +02:00
07d25cd69d main: Use GLib's structured logging support
We still use our own copy of a libgsystem method for structured
logging, but since then GLib has gained (introspectable) API for
that functionality, so switch to that.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/579
2019-06-15 15:26:17 +02:00
520cea9394 iconGrid: Don't hide children inside allocation loop
Hiding a child implies a parent reallocation, and IconGrid does it for the
children that doesn't fit in the available space, but this could lead to an
allocation recursion cycle. This has been introduced by commit 0e0574a0 to
reduce CPU usage not to using JS vfuncs.

To avoid this, toggle the children opacity instead so that we can achieve the
same visibility result, without any reallocation need.
In this way we also fix the case where hidden children can be shown again,
as _getVisibleChildren doesn't filter-out transparent ones, restoring the
pre-commit 0e0574a0 behavior.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/559
2019-06-15 12:31:50 +00:00
58c4212cfa shell-app: Fix spelling error
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1205
2019-06-15 12:08:40 +02:00
7059e31f6a background: Group 'changed' signal emission
Background is monitoring the whole `org.gnome.desktop.background` gsettings keys
for changes connecting to the non-specialized 'changed' signal and re-emitting
this as-is.
This means that when the background is changed via control-center, we get
multiple 'changed' signal events from GSettings, and for each one of this we
recreate a Background and a BackgroundActor.

Avoid this by using an idle to delay the emission of the 'changed' signal
grouping the events.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558
2019-06-14 12:24:20 +00:00
a9234f7631 background: Use Garbage Collector to dispose background
The same Meta.Background could be used by multiple instances of background
actors, and so should not be disposed when the actor using it is destroyed.

Instead of calling `run_dispose` directly on it, just nullify the reference
on destroy method, leaving the job of doing the proper disposition to the
gabage collector that keeps the proper reference count on the Meta.Background.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/558
2019-06-14 12:24:20 +00:00
1e5a8b0cd7 Update Indonesian translation 2019-06-14 10:36:04 +00:00
5ef343f245 Update Friulian translation 2019-06-11 09:26:26 +00:00
22e33b4c47 Updated Spanish translation 2019-06-10 12:05:19 +02:00
5ace4682bf accessibility: Add pointer accessibility support
Adds the UI part for the pointer accessibility features.

The various timeouts running are notified using a pie-timer showing
under the pointer.

For dwell-click type selection, we use a drop-down menu. Users can
use the dwell-click to select the next type of dwell click to be
emitted.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/474
2019-06-06 09:13:29 +02:00
14d9839ed3 theme: Add pointer accessibility resources
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/474
2019-06-06 09:13:29 +02:00
3b6fae582b sessionMode: add a property to disable window manager menus
We will use this to disable menus in the initial-setup session.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/569
2019-06-06 01:25:04 +00:00
3cbdf4f9a5 remoteSearch: exclude content from hidden apps
Some apps may be configured as NoDisplay=true, but still install
a search provider.
Like we do elsewhere, exclude them from showing up in the UI.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/568
2019-06-05 16:15:42 -07:00
d8825e0d12 shell: Stop using anchor point
Since the removal of the old (pre-3.16) message tray, legacy tray icons
are very unlikely to be placed in a container that is animated using the
deprecated anchor point.

Just assume that the regular stage position is good enough.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/572
2019-06-05 17:59:51 +00:00
3c5fea59df st: Stop using (deprecated) ClutterAnimation
Instead, make StAdjustment a ClutterAnimatable and use a property
transition.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/572
2019-06-05 17:59:51 +00:00
443c8347ea locatePointer: Add implementation in gnome-shell
The "locate pointer" functionality was implemented in gnome settings
daemon using X11 protocols and would fail when run under Wayland.

With Wayland, there is no global coordinate space exposed to the clients
so this functionality cannot be implemented as a separate program.

Instead, add the "locate pointer" functionality in gnome-shell so that
it works in both X11 and Wayland.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/413
https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
2019-06-05 08:15:10 +00:00
ee3f52c097 layout: Use the ripples for overview
As we moved the ripples implementation different class of its own, use
that for switching to overview.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/413
https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
2019-06-05 08:15:10 +00:00
4b01bb6f99 ripples: Add a new class ripples
So we can use the same code for both the ripples in overview and the
pointer location.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/981
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/413
https://gitlab.gnome.org/GNOME/mutter/merge_requests/453
https://gitlab.gnome.org/GNOME/gsettings-desktop-schemas/merge_requests/19
https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/86
2019-06-05 08:15:10 +00:00
27ef8154dc Updated Spanish translation 2019-06-03 12:25:50 +02:00
0a7e717e0e Update Hungarian translation 2019-06-01 11:17:41 +00:00
2d2824b947 Update Indonesian translation 2019-05-31 03:52:30 +00:00
40c2a403ac search: reload search providers when installed applications change
Otherwise, a shell restart will be required after installing a new
application, before its results can be seen in search.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/562
2019-05-29 20:33:16 +00:00
238b87d386 grabHelper: Throw an error if the owner is not an actor
Starting from commit 7bb84dae, GrabHelper requires the owner to be an Actor as
we pass this to pushModal that assumes it to be as well.

So check that GrabHelper owner is an actor and throws an error if it is not the
case. This helps in tracking down issues such as gnome-shell-extensions!68

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/565
2019-05-29 15:13:00 -05:00
8c01d341c7 PopupMenuManager: Remove unneeded _owner reference
Nothing inside PopupMenuManager is using the owner, while a reference of it is
already owned by the GrabHelper, so remove this dead property.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/565
2019-05-29 15:13:00 -05:00
866629b3d3 windowManager: Disable favorite shortcuts without overview
The `switch-to-application-n` shortcuts are essentially "launch the nth
app in the dash" actions, so they are at the very least confusing when
the dash isn't available because the overview itself is disabled (for
example in initial-setup mode).

So disable the shortcuts when the overview is disabled, but delegate the
decision to a separate function so that extensions like 'panel-favorites'
which expose favorites by some other means can easily re-enable them.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1333
2019-05-29 20:03:59 +00:00
2b3ab3ecec windowMenu: Do actions requiring grab once ungrabbed
Resizing or moving a window needs starting a keyboard grab. However, if the
action is triggered by a menu entry activation it might not work as we already
have already an active grab on input devices to manage the menu itself.

So, possibly wait maximum 100ms for the current grab operation to be completed
before trying go start a new one.

Needs https://gitlab.gnome.org/GNOME/mutter/merge_requests/596
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1326

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/557
2019-05-29 12:04:26 -05:00
759120b95f popupMenu: Connect after to item 'activate' signal
A menu item activation might lead to a call to `itemActivated` which eventually
will close the menu which leads to a `PopupMenu.removeAll` that destroys all the
items, stopping the emission of the 'activate' signal for them.

Before commit 4258ae3e this was not happening because destroy'ing a javascript
object wasn't really disposing it and thus stopping the signal emissions.

So, ensure that `itemActivated` is called after that all the other callbacks
have been consumed, and so that the menu is closed as last thing.

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/557
2019-05-29 12:04:26 -05:00
de0e21612c meson: Do not add compiler flags if 'plain' buildtype is used
That is how the 'plain' buildtype is meant in meson.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/464
2019-05-29 17:14:56 +02:00
83e83444db meson: Add some compiler arguments to debug builds
To get better debug information.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/464
2019-05-29 17:14:56 +02:00
5060aee7b2 shellMountOperation: Use a Unicode apostrophe in a new string
See https://developer.gnome.org/hig/stable/typography.html
2019-05-28 19:14:19 +02:00
12bace2721 shell-global: don't warn when unsetting non-existent state
If the state we're trying to delete does not exist, do not log an
error.
Prevents this journal warning at startup:

gnome-shell[1082]: Could not delete runtime/persistent state file: Error removing file /run/user/1000/gnome-shell/runtime-state-LE.:0/screenShield.locked: No such file or directory

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
2019-05-27 08:36:17 -07:00
2c45b5416e keyring-prompt: relax NULL check in remove_mnemonics()
Instead of considering a GValue containing a NULL string to be a
programmer error, simply return NULL.
remove_mnemonics() is in fact called on the value of the
"choice-label" property as well, which has NULL as its default
value.

This prevents triggering the following gnome-shell warning:

gnome-shell[1082]: remove_mnemonics: assertion 'label != NULL' failed

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
2019-05-27 08:36:11 -07:00
96c2473317 modemManager: improve check for CDMA system identifier
Upon construction of the CDMA modem proxy, _reloadCdmaOperatorName()
is called and the value of the Sid property is read.
That property is defined as UINT32 in the D-Bus interface, but the
value may not be loaded yet after the proxy is constructed, in which
case its value will be null.

In _findProviderForSid(), we'll end up calling lookup_cdma_sid(null)
which fails with the following assertion:

gnome-shell[1082]: nma_mobile_providers_database_lookup_cdma_sid: assertion 'sid > 0' failed

This commit changes the (sid == 0) check in _findProviderForSid()
to (!sid) which will also catch the null case.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
2019-05-27 08:36:05 -07:00
6359d6ef30 windowAttentionHandler: disconnect signals before destruction
The 'destroy' signal is emitted at the end of the destroy() method.
However the implementation of destroy() can end up emitting one of the
signals we connect to on the window, causing us to re-enter destroy
from its callback.
That will in turn lead to some objects getting disposed twice, which
produces a stack trace like the following one.

This commit fixes the issue by overriding the destroy() method instead
of connecting to the signal, which allows us to disconnect the signal
handlers from the window at an earlier time and avoid re-entrancy.

--

gnome-shell[1082]: Object Gio.Settings (0x7f0af8143f00), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
org.gnome.Shell.desktop[1082]: #0   5627f9e801a8 i   resource:///org/gnome/shell/ui/messageTray.js:238 (7f0aefa9eca0 @ 22)
org.gnome.Shell.desktop[1082]: #1   5627f9e80108 i   resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
org.gnome.Shell.desktop[1082]: #2   5627f9e80070 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
org.gnome.Shell.desktop[1082]: #3   7fffa69fbfc0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #4   5627f9e7ffe0 i   resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
org.gnome.Shell.desktop[1082]: #5   5627f9e7ff38 i   resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
org.gnome.Shell.desktop[1082]: #6   5627f9e7fe80 i   resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
org.gnome.Shell.desktop[1082]: #7   5627f9e7fde8 i   resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
org.gnome.Shell.desktop[1082]: #8   7fffa69ff8e0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #9   7fffa69ff9d0 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #10   5627f9e7fd58 i   resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
org.gnome.Shell.desktop[1082]: #11   5627f9e7fcb8 i   resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
org.gnome.Shell.desktop[1082]: #12   5627f9e7fc28 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
org.gnome.Shell.desktop[1082]: #13   5627f9e7fb80 i   resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
org.gnome.Shell.desktop[1082]: #14   5627f9e7fad0 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
org.gnome.Shell.desktop[1082]: #15   5627f9e7fa58 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
org.gnome.Shell.desktop[1082]: #16   7fffa6a03350 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #17   5627f9e7f9d0 i   resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
org.gnome.Shell.desktop[1082]: #18   5627f9e7f950 i   resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
org.gnome.Shell.desktop[1082]: #19   7fffa6a048f0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: == Stack trace for context 0x5627f7d1e220 ==
org.gnome.Shell.desktop[1082]: #0   5627f9e801a8 i   resource:///org/gnome/shell/ui/messageTray.js:239 (7f0aefa9eca0 @ 42)
org.gnome.Shell.desktop[1082]: #1   5627f9e80108 i   resource:///org/gnome/shell/ui/messageTray.js:802 (7f0aefaa2ee0 @ 28)
org.gnome.Shell.desktop[1082]: #2   5627f9e80070 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:79 (7f0aef7b29d0 @ 62)
org.gnome.Shell.desktop[1082]: #3   7fffa69fbfc0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #4   5627f9e7ffe0 i   resource:///org/gnome/shell/ui/messageTray.js:121 (7f0aefa9e1f0 @ 71)
org.gnome.Shell.desktop[1082]: #5   5627f9e7ff38 i   resource:///org/gnome/shell/ui/messageTray.js:1408 (7f0aefaa58b0 @ 22)
org.gnome.Shell.desktop[1082]: #6   5627f9e7fe80 i   resource:///org/gnome/shell/ui/messageTray.js:1237 (7f0aefaa51f0 @ 729)
org.gnome.Shell.desktop[1082]: #7   5627f9e7fde8 i   resource:///org/gnome/shell/ui/messageTray.js:1055 (7f0aefaa3d30 @ 124)
org.gnome.Shell.desktop[1082]: #8   7fffa69ff8e0 b   self-hosted:979 (7f0aefa515e0 @ 440)
org.gnome.Shell.desktop[1082]: #9   7fffa69ff9d0 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #10   5627f9e7fd58 i   resource:///org/gnome/shell/ui/messageTray.js:479 (7f0aefaa0940 @ 50)
org.gnome.Shell.desktop[1082]: #11   5627f9e7fcb8 i   resource:///org/gnome/shell/ui/messageTray.js:808 (7f0aefaa2ee0 @ 99)
org.gnome.Shell.desktop[1082]: #12   5627f9e7fc28 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:69 (7f0aef7b28b0 @ 13)
org.gnome.Shell.desktop[1082]: #13   5627f9e7fb80 i   resource:///org/gnome/shell/ui/main.js:566 (7f0aefcd8820 @ 216)
org.gnome.Shell.desktop[1082]: #14   5627f9e7fad0 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:103 (7f0aef7b2c10 @ 27)
org.gnome.Shell.desktop[1082]: #15   5627f9e7fa58 i   resource:///org/gnome/shell/ui/windowAttentionHandler.js:43 (7f0aef7b2700 @ 17)
org.gnome.Shell.desktop[1082]: #16   7fffa6a03350 b   resource:///org/gnome/gjs/modules/signals.js:142 (7f0aefccb670 @ 386)
org.gnome.Shell.desktop[1082]: #17   5627f9e7f9d0 i   resource:///org/gnome/shell/ui/messageTray.js:471 (7f0aefaa08b0 @ 22)
org.gnome.Shell.desktop[1082]: #18   5627f9e7f950 i   resource:///org/gnome/shell/ui/calendar.js:752 (7f0aefaabdc0 @ 22)
org.gnome.Shell.desktop[1082]: #19   7fffa6a048f0 b   self-hosted:979 (7f0aefa515e0 @ 440)
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed
gnome-shell[1082]: Object Gio.Settings (0x7f0af8161750), has been already deallocated — impossible to access it. This might be caused by the object having been destroyed from C code using something such as destroy(), dispose(), or remove() vfuncs.
gnome-shell[1082]: g_object_run_dispose: assertion 'G_IS_OBJECT (object)' failed

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/555
2019-05-27 08:35:56 -07:00
2f6323afc2 modalDialog: Use a Gobject property to manage the state
Make the state read-only while add a "private" function to set it and notify
when it changes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/55
2019-05-24 16:28:18 -05:00
d25bcbc3a7 modalDialog: Inherit from St.Widget
Make the dialog a widget itself, removing the `_group` property used for
handling the actor.

Update all the inherited classes to be also GObject implementations, moving all
the signals to proper object ones.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/55
2019-05-24 16:27:25 -05:00
dd5d7d3b70 shell: Only initialize global->xdisplay on X11 compositors
This is just used to set up things that are relevant to X11 compositors
(XDND, XFixes input region). We can live with it unset on the wayland
compositor cases.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/378
2019-05-24 12:24:06 +02:00
771b1a0788 shell: Do not set XFixes input region on wayland compositors
This is just needed on the X11 compositor, wayland compositors are known
for handling their own input.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/378
2019-05-24 12:24:06 +02:00
5a9d094f3e shell: Use MetaDisplay input focus API
Replaces use of (now removed) MetaX11Display focus API (which happened to
work for wayland too).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/378
2019-05-24 12:24:06 +02:00
9ca8433170 network: Make NMWirelessDialogItem a subclass of St.BoxLayout
In commit 41dd744b74 this item was
confused with a popup menu item. To fix this, make NMWirelessDialogItem
inherit from St.BoxLayout instead of adding the item.actor variable back
again.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/551
2019-05-22 19:55:49 +00:00
177 changed files with 8854 additions and 5169 deletions

6
.eslintrc.json Normal file
View File

@ -0,0 +1,6 @@
{
"extends": [
"./lint/eslintrc-gjs.json",
"./lint/eslintrc-shell.json"
]
}

53
NEWS
View File

@ -1,3 +1,56 @@
3.33.4
======
* Fix unintentional interference between gestures [Jonas; !598]
* Fix unintentional loop while polkit dialog is active [Ray; !602]
* Fix alt-tab icon size on HiDPI [Jonas; !587]
* Style fixes and improvements [Frederik, Jakub; !610, #1446, #1449]
* Fix style updates for non-background CSS properties [Florian; #1212]
* Fix cursor visibility in screen recordings [Illya; #1208]
* Add option for disabling the hot corner [Florian; #688320]
* Use more fine-grained levels in battery indicator [Florian; !561, #1442]
* Fix the calculation of the maximum number of app search results [Jonas; !110]
* Handle horizontal workspace layout with gestures/animations [Florian; !575]
* Improve handling of session mode extensions [Florian, Didier; #789852]
* Misc. bug fixes and cleanups [Jonas, Florian, Sonny, Carlos, Mario, Benjamin,
Marco, Ting-Wei; !599, !600, !591, !606, !152, !607, !604, !495, !608, !611,
!614, !612, !615, !618, #369, !620, #774, !621, !616, #1065, !609, !626,
!491, !631, !632, !633, #1457]
Contributors:
Benjamin Berg, Jonas Dreßler, Frederik Feichtmeier, Carlos Garnacho,
Illya Klymov, Ting-Wei Lan, Florian Müllner, Sonny Piers, Mario Sanchez Prada,
Didier Roche, Jakub Steiner, Ray Strode, Jor Teron, Marco Trevisan (Treviño)
Translators:
Jordi Mas [ca], Jor Teron [mjw]
3.33.3
======
* Prepare for optional X11 [Carlos; !378]
* Fix opening window menu [Marco; !557]
* Reload search providers when installed applications change [Cosimo; !562]
* Implement locate-pointer accessibility feature [Olivier; #981]
* Allow to disable window menus via session mode [Cosimo; !569]
* Implement mouse accessibility [Olivier; !474]
* Call GDM's RegisterSession() after startup [Iain; !570]
* Fix extended keys popups being hidden by on-screen keyboard [Marco; !583]
* Fix top bar being hidden by lock screen [Jonas; !571]
* Update theme to better match GTK's Adwaita [Frederik; #841]
* Set up GJS profiler when GJS_TRACE_FD is set [Christian; !573]
* Misc. bug fixes and cleanups [Jonas, Cosimo, Robert, Florian, Marco, Simon,
Laurent, Niels, Will; !551, !555, !464, #1333, !565, !572, !568, !558, #1205,
#1336, !579, !576, #1392, !582, !586, #1406, #1351]
Contributors:
Laurent Bigonville, Cosimo Cecchi, Piotr Drąg, Jonas Dreßler,
Frederik Feichtmeier, Olivier Fourdan, Carlos Garnacho, Niels De Graef,
Christian Hergert, Iain Lane, Robert Mader, Florian Müllner, Simon Schampijer,
Jakub Steiner, Will Thompson, Marco Trevisan (Treviño)
Translators:
Kukuh Syafaat [id], Balázs Meskó [hu], Daniel Mustieles [es],
Fabio Tomat [fur], Nathan Follens [nl], Goran Vidović [hr], Jordi Mas [ca]
3.33.2
======
* Fix keeping actors visible in scrollviews [Marco; #1061]

View File

@ -173,6 +173,30 @@
<arg type="s" direction="in" name="uuid"/>
</method>
<!--
EnableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Enable an extension.
-->
<method name="EnableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!--
DisableExtension:
@uuid: The UUID of the extension
@success: Whether the operation was successful
Disable an extension.
-->
<method name="DisableExtension"> \
<arg type="s" direction="in" name="uuid"/> \
<arg type="b" direction="out" name="success"/> \
</method> \
<!--
LaunchExtensionPrefs:
@uuid: The UUID of the extension
@ -189,6 +213,15 @@
-->
<method name="CheckForUpdates"/>
<signal name="ExtensionStateChanged">
<arg type="s" name="uuid"/>
<arg type="a{sv}" name="state"/>
</signal>
<!--
ExtensionStatusChanged:
Deprecated for ExtensionStateChanged
-->
<signal name="ExtensionStatusChanged">
<arg type="s" name="uuid"/>
<arg type="i" name="state"/>

View File

@ -9,7 +9,7 @@
<method name="ShowOSD">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="ShowMonitorLabels2">
<method name="ShowMonitorLabels">
<arg type="a{sv}" direction="in" name="params"/>
</method>
<method name="HideMonitorLabels"/>

View File

@ -20,10 +20,16 @@
<file>no-notifications.svg</file>
<file>noise-texture.png</file>
<file>pad-osd.css</file>
<file alias="icons/pointer-double-click-symbolic.svg">pointer-double-click-symbolic.svg</file>
<file alias="icons/pointer-drag-symbolic.svg">pointer-drag-symbolic.svg</file>
<file alias="icons/pointer-primary-click-symbolic.svg">pointer-primary-click-symbolic.svg</file>
<file alias="icons/pointer-secondary-click-symbolic.svg">pointer-secondary-click-symbolic.svg</file>
<file>process-working.svg</file>
<file>toggle-off-intl.svg</file>
<file>toggle-off.svg</file>
<file>toggle-off-dark.svg</file>
<file>toggle-off-hc.svg</file>
<file>toggle-on-intl.svg</file>
<file>toggle-on.svg</file>
<file>toggle-on-dark.svg</file>
<file>toggle-on-hc.svg</file>
</gresource>
</gresources>

View File

@ -21,6 +21,17 @@
EnableExtension and DisableExtension D-Bus methods on org.gnome.Shell.
</description>
</key>
<key name="disabled-extensions" type="as">
<default>[]</default>
<summary>UUIDs of extensions to force disabling</summary>
<description>
GNOME Shell extensions have a UUID property; this key lists extensions
which should be disabled, even if loaded as part of the current mode.
You can also manipulate this list with the EnableExtension and
DisableExtension D-Bus methods on org.gnome.Shell.
This key takes precedence over the “enabled-extensions” setting.
</description>
</key>
<key name="disable-user-extensions" type="b">
<default>false</default>
<summary>Disable user extensions</summary>
@ -99,7 +110,6 @@
</description>
</key>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
<child name="keyboard" schema="org.gnome.shell.keyboard"/>
</schema>
<schema id="org.gnome.shell.keybindings" path="/org/gnome/shell/keybindings/"
@ -183,17 +193,6 @@
</key>
</schema>
<schema id="org.gnome.shell.keyboard" path="/org/gnome/shell/keyboard/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="keyboard-type" type="s">
<default>'touch'</default>
<summary>Which keyboard to use</summary>
<description>
The type of keyboard to use.
</description>
</key>
</schema>
<schema id="org.gnome.shell.app-switcher"
path="/org/gnome/shell/app-switcher/"
gettext-domain="@GETTEXT_PACKAGE@">

View File

@ -1,3 +1,5 @@
$variant: 'light';
@import "gnome-shell-sass/_high-contrast-colors"; //use gtk colors
@import "gnome-shell-sass/_drawing";
@import "gnome-shell-sass/_common";

View File

@ -3,11 +3,11 @@
$base_color: if($variant == 'light', #ffffff, lighten(desaturate(#241f31, 20%), 2%));
$bg_color: if($variant == 'light', #f6f5f4, desaturate(#3d3846, 10%));
$bg_color: if($variant == 'light', #f6f5f4, darken(desaturate(#3d3846, 100%), 4%));
$fg_color: if($variant == 'light', #2e3436, #eeeeec);
$selected_fg_color: #ffffff;
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 20%));
$selected_bg_color: if($variant == 'light', #3584e4, darken(#3584e4, 10%));
$selected_borders_color: if($variant== 'light', darken($selected_bg_color, 15%), darken($selected_bg_color, 30%));
$borders_color: if($variant == 'light', darken($bg_color, 18%), darken($bg_color, 10%));
$borders_edge: if($variant == 'light', transparentize(white, 0.2), transparentize($fg_color, 0.93));
@ -21,11 +21,15 @@ $success_color: if($variant == 'light', #33d17a, darken(#33d17a, 10%));
$destructive_color: if($variant == 'light', #e01b24, darken(#e01b24, 10%));
$osd_fg_color: #eeeeec;
$osd_bg_color: #2e3436;
$osd_text_color: white;
$osd_bg_color: transparentize(darken(desaturate(#3d3846, 100%), 12%),0.04);
$osd_insensitive_bg_color: transparentize(mix($osd_fg_color, opacify($osd_bg_color, 1), 10%), 0.5);
$osd_insensitive_fg_color: mix($osd_fg_color, opacify($osd_bg_color, 1), 50%);
$osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);
$osd_outer_borders_color: transparentize(white, 0.84);
$tooltip_borders_color: $osd_outer_borders_color;
$shadow_color: transparentize(black, 0.9);
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);

File diff suppressed because it is too large Load Diff

View File

@ -37,16 +37,13 @@
// possible $t values:
// normal, focus, insensitive
//
$_inner_shadows: inset 0 2px 4px transparentize(black, 0.6);
@if $t==normal {
background-color: $base_color;
border-color: $borders_color;
@include _shadows($_inner_shadows);
}
@if $t==focus {
@include _shadows($_inner_shadows);
border-color: if($fc==$selected_bg_color,
$selected_borders_color,
darken($fc,35%));
@ -111,7 +108,7 @@
}
}
@mixin button($t, $c:$osd_bg_color, $tc:$fg_color, $edge: $borders_edge) {
@mixin button($t, $c:$bg_color, $tc:$fg_color, $edge: $borders_edge) {
//
// Button drawing function
//
@ -130,46 +127,39 @@
$_hilight_color: _button_hilight_color($c);
$_button_edge: if($edge == none, none, _widget_edge($edge));
$_blank_edge: if($edge == none, none, _widget_edge(transparentize($edge,1)));
$_button_shadow: 0 1px 2px transparentize($shadow_color, 0.03);
@if $t==normal {
//
// normal button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.5),
$osd_bg_color);
color: $osd_fg_color;
background-color: $_bg;
border-color: $osd_borders_color;
box-shadow: inset 0 1px lighten($osd_bg_color,10%);
color: $tc;
background-color: $c;
border-color: $borders_color;
box-shadow: $_button_shadow;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
}
@if $t==focus {
//
// focused button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
color: $osd_fg_color;
//
color: $tc;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
box-shadow: inset 0px 0px 0px 2px $selected_bg_color;
//border-color: $selected_bg_color;
}
@else if $t==hover {
//
// active osd button
//
$_bg: if($c!=$osd_bg_color, transparentize($c, 0.3),
lighten($osd_bg_color,3%));
color: white;
border-color: $osd_borders_color;
background-color: $_bg;
box-shadow: inset 0 1px lighten($osd_bg_color,20%);
color: $tc;
border-color: $borders_color;
background-color: $c;
box-shadow: $_button_shadow;
text-shadow: 0 1px black;
icon-shadow: 0 1px black;
@ -178,27 +168,18 @@
//
// active osd button
//
$_bg: if($c!=$bg_color, $c, $osd_borders_color);
color: white;
border-color: $osd_borders_color;
background-color: $selected_bg_color;
// This should be none, but it's creating some issues with borders, so to
// workaround it for now, use inset wich goes through a different code path.
// see https://bugzilla.gnome.org/show_bug.cgi?id=752934
box-shadow: inset 0 0 black;
color: $tc;
border-color: $borders_color;
background-color: $c;
text-shadow: none;
icon-shadow: none;
box-shadow: none;
}
@else if $t==insensitive {
//
// insensitive osd button
//
$_bg: transparentize(mix($insensitive_fg_color,$osd_bg_color,20%),0.3);
color: $insensitive_fg_color;
border-color: $osd_borders_color;
background-color: $_bg;
border-color: $insensitive_borders_color;
background-color: $insensitive_bg_color;
box-shadow: none;
text-shadow: none;
icon-shadow: none;

View File

@ -26,6 +26,7 @@ $osd_borders_color: transparentize(black, 0.3);
$osd_outer_borders_color: transparentize(white, 0.9);
$tooltip_borders_color: $osd_outer_borders_color;
$shadow_color: transparentize(black, 0.9);
//insensitive state derived colors
$insensitive_fg_color: mix($fg_color, $bg_color, 50%);

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="layer1"
style="display:inline">
<g
id="id1"
transform="translate(-19,-0.75)">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 19.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.38151 2.829427,-2.763021 4.24414,-4.144531 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 0.01057,-0.470226 -0.405577,-0.908445 -0.434651,-1.313638 0.259401,-0.25321 0.518802,-0.50642 0.778203,-0.75963 0.5882,1.18866 1.158389,2.386561 1.758464,3.569127 1.108631,1.640259 4.157538,0.465128 3.89799,-1.495859 -0.192325,-0.904303 -0.717854,-1.698026 -1.068629,-2.548967 -0.238908,-0.512658 -0.477817,-1.025315 -0.716725,-1.537973 1.755859,0 3.511719,0 5.267578,0 C 34.777352,9.738932 30.31641,5.0970051 25.855469,0.45507812 c 0,2.08138018 0,4.16276048 0,6.24414068 -2,-2.0813802 -4,-4.1627605 -6,-6.24414068 z m 1.5,3.72656248 c 2,2.0813801 4,4.1627603 6,6.2441404 0,-2.0813801 0,-4.1627603 0,-6.2441404 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.366537,0 -2.733073,0 -4.09961,0 0.883468,1.903435 1.781983,3.800273 2.656081,5.707817 0.0065,0.622781 -1.227555,0.980575 -1.325116,0.207118 -0.80433,-1.640251 -1.608661,-3.280501 -2.412991,-4.920752 -1.020182,0.995443 -2.040365,1.990885 -3.060547,2.986328 0.263642,0.608048 0.596803,1.192457 0.814693,1.816134 -0.182662,0.601037 -1.26833,0.8373 -1.365856,0.06795 -0.796094,-1.623456 -1.592189,-3.246912 -2.388284,-4.870368 -1.059245,1.033854 -2.118489,2.067708 -3.177734,3.101562 -4e-6,-4.265002 -7e-6,-8.5300036 -1.1e-5,-12.7950054 z"
id="path5565" />
</g>
<g
id="id2"
transform="translate(-25,-0.75)" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="g835">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="M 10.705078 1.671875 C 9.8685536 1.7465699 8.886927 1.5353073 8.2578125 2.2480469 C 8.0785627 2.7511513 7.8667422 2.9777446 7.3125 2.8652344 C 6.5186841 2.8141575 5.6105879 2.9190179 5.125 3.6386719 C 4.5700923 4.4696324 4.8113194 5.4949043 4.7578125 6.4316406 L 4.7578125 7.9335938 C 4.2480917 7.6156216 3.6258927 7.8015358 3.0585938 7.7519531 C 2.6157606 7.7312277 2.1774807 7.7771069 1.7402344 7.84375 C 1.7971654 10.529678 1.813967 13.217089 1.8613281 15.902344 C 1.9550191 17.204635 3.0933719 18.307155 4.40625 18.326172 C 5.0391993 18.341272 5.8885801 18.332951 6.6308594 18.337891 C 9.8526764 18.325821 13.076973 18.38774 16.296875 18.28125 C 17.459088 18.161027 18.510143 17.092798 18.367188 15.884766 L 18.367188 6.4042969 C 17.660379 5.4636119 16.551912 4.623434 15.308594 4.8339844 C 15.009045 4.3804158 14.822476 3.3608651 14.082031 3.0351562 C 13.727176 2.744118 13.242443 2.9253873 12.822266 2.8730469 C 12.524824 2.8003648 11.966366 3.0655864 11.953125 2.6210938 C 11.795774 2.0995736 11.23789 1.7125276 10.705078 1.671875 z M 10.599609 3.1757812 C 10.764131 3.4472414 10.782382 3.9294982 10.818359 4.3007812 C 10.824915 4.3076775 10.838155 4.3066925 10.845703 4.3125 C 10.836598 4.3123268 10.827465 4.3126732 10.818359 4.3125 L 11.3125 10.212891 L 11.976562 4.3710938 L 13.322266 4.375 C 13.858345 4.7645492 13.735252 5.5154752 13.876953 6.0976562 C 13.865826 6.1651282 13.88335 6.1937019 13.892578 6.234375 C 13.891928 6.2343667 13.891276 6.2343833 13.890625 6.234375 L 13.902344 6.3203125 L 14.384766 10.185547 L 15.048828 6.265625 C 15.622863 6.228498 16.206517 6.3041365 16.607422 6.7675781 C 17.017062 6.9844433 16.823063 7.4565491 16.867188 7.8261719 L 16.867188 16.167969 C 16.530129 17.131654 15.267211 16.71624 14.492188 16.828125 C 11.121671 16.841205 7.7500508 16.861953 4.3808594 16.814453 C 3.4051926 16.786173 3.2389196 15.744474 3.3398438 14.972656 C 3.3282027 13.065594 3.2950998 11.158732 3.2617188 9.2519531 C 3.5880829 9.2584131 3.9376766 9.2391948 4.25 9.2617188 C 4.7438842 10.17694 4.7346154 11.262903 4.7578125 12.277344 C 5.2504494 12.270544 5.8011939 12.317174 6.2578125 12.277344 C 6.2669593 9.7577406 6.2393741 7.2373172 6.2714844 4.71875 C 6.3763823 4.198849 7.0022289 4.409587 7.3828125 4.3652344 L 8.0585938 4.3652344 L 8.546875 10.212891 L 9.2167969 4.3359375 L 9.2128906 4.3359375 C 9.2438386 3.9531035 9.0622615 3.4401006 9.4609375 3.2167969 L 10.599609 3.1757812 z "
id="path5630" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2"
version="1.1">
<g
id="layer1"
style="display:inline">
<g
id="id1"
transform="translate(-22.25,-0.75)">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
id="path5565" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="20"
height="20"
id="svg2">
<g
id="layer1"
style="display:inline;stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
<g
transform="matrix(-1,0,0,1,42,-0.75)"
id="g5847"
style="stroke-width:1.5;stroke-miterlimit:4;stroke-dasharray:none;stroke:#000000;stroke-opacity:1">
<path
style="color:#000000;shape-padding:0;clip-rule:nonzero;display:block;overflow:visible;visibility:visible;opacity:1;solid-color:#000000;solid-opacity:1;fill:#464646;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;enable-background:accumulate"
d="m 25.855469,0.45507812 c 0,6.69466128 0,13.38932288 0,20.08398388 1.414713,-1.380859 2.829427,-2.761719 4.24414,-4.142578 0.612408,1.215372 1.173049,2.460221 1.819709,3.656095 1.141947,1.476279 3.975266,0.389006 3.846009,-1.473608 -0.09413,-0.822519 -0.594755,-1.521423 -0.899969,-2.277599 -0.298869,-0.640171 -0.597739,-1.280342 -0.896608,-1.920513 1.75651,0 3.513021,0 5.269531,0 C 34.777344,9.738932 30.316406,5.0970051 25.855469,0.45507812 Z m 1.5,3.72656248 c 2.786458,2.8997395 5.572917,5.7994789 8.359375,8.6992184 -1.367188,0 -2.734375,0 -4.101563,0 0.885072,1.903196 1.781799,3.80152 2.659622,5.707744 0.0349,0.566084 -1.149057,0.988823 -1.282093,0.297971 -0.818567,-1.671162 -1.637133,-3.342323 -2.455699,-5.013485 -1.059896,1.034505 -2.119791,2.06901 -3.179687,3.103515 1.5e-5,-4.264988 3e-5,-8.5299756 4.5e-5,-12.7949634 z"
id="path5851" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-42.76)"/></defs><g transform="translate(0 -291.18)" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#323233" stroke="#272728"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none" fill="url(#b)" stroke="#151515"/></g></svg>

After

Width:  |  Height:  |  Size: 725 B

View File

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="46"
height="22"
viewBox="0 0 46 22"
version="1.1"
id="svg2751"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="toggle-off-intl.svg">
<defs
id="defs2745">
<linearGradient
inkscape:collect="always"
id="linearGradient3329">
<stop
style="stop-color:#39393a;stop-opacity:1;"
offset="0"
id="stop3325" />
<stop
style="stop-color:#302f30;stop-opacity:1"
offset="1"
id="stop3327" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3329"
id="linearGradient3331"
x1="53"
y1="294.42917"
x2="53"
y2="309.80417"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-42.760724)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#535353"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="-19.436775"
inkscape:cy="-13.499723"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="true"
borderlayer="true"
inkscape:showpageshadow="false"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid3298" />
</sodipodi:namedview>
<metadata
id="metadata2748">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17916)">
<rect
style="opacity:1;vector-effect:none;fill:#323233;fill-opacity:1;stroke:#272728;stroke-width:1.08532763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
id="rect3296"
width="44.446434"
height="20.910645"
x="0.625"
y="291.71494"
rx="10.455324"
ry="10.073335" />
<rect
ry="10.455322"
rx="10.455322"
y="291.71494"
x="0.5428465"
height="20.910645"
width="21.142862"
id="rect3300"
style="opacity:1;vector-effect:none;fill:url(#linearGradient3331);fill-opacity:1;stroke:#151515;stroke-width:1.08532763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#e1dedb" stroke="#cdc7c2" stroke-linecap="round" stroke-linejoin="round"/><rect ry="10.455" rx="10.455" y="291.715" x=".543" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke="#aa9f98" stroke-linecap="round" stroke-linejoin="round"/><g transform="matrix(.97148 0 0 1 1658.914 -2552.91)" stroke-width="1.015" stroke-linecap="round" stroke-linejoin="round"><rect ry="13.17" rx="13.556" y="1234.681" x="-1242.732" height="26" width="49.409" style="marker:none" fill="#e1dedb" stroke="#cdc7c2"/><rect style="marker:none" width="26.763" height="26" x="-1242.732" y="1234.769" rx="13.511" ry="13.126" fill="#f8f7f7" stroke="#aa9f98"/></g><g transform="matrix(.97148 0 0 1 1658.914 -2512.91)" stroke-width="1.015" stroke="#2b73cc"><rect style="marker:none" width="49.409" height="26" x="-1242.732" y="1234.681" rx="13.556" ry="13.17" fill="#3081e3"/><rect ry="13.126" rx="13.511" y="1234.769" x="-1220.086" height="26" width="26.763" style="marker:none" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></g></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="46" height="22"><defs><linearGradient id="a"><stop offset="0" stop-color="#39393a"/><stop offset="1" stop-color="#302f30"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="53" y1="294.429" x2="53" y2="309.804" gradientUnits="userSpaceOnUse" gradientTransform="translate(-19)"/></defs><g transform="translate(0 -291.18)" stroke="#030e1b" stroke-width="1.085"><rect style="marker:none" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#15539e"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none" fill="url(#b)"/></g></svg>

After

Width:  |  Height:  |  Size: 707 B

View File

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="46"
height="22"
viewBox="0 0 46 22"
version="1.1"
id="svg2751"
inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="toggle-on-intl.svg">
<defs
id="defs2745">
<linearGradient
inkscape:collect="always"
id="linearGradient3329">
<stop
style="stop-color:#39393a;stop-opacity:1;"
offset="0"
id="stop3325" />
<stop
style="stop-color:#302f30;stop-opacity:1"
offset="1"
id="stop3327" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient3329"
id="linearGradient3331"
x1="53"
y1="294.42917"
x2="53"
y2="309.80417"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(-19)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#535353"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="1"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="13.588971"
inkscape:cy="14.124546"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:pagecheckerboard="true"
borderlayer="true"
inkscape:showpageshadow="false"
showborder="false">
<inkscape:grid
type="xygrid"
id="grid3298" />
</sodipodi:namedview>
<metadata
id="metadata2748">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-291.17916)">
<rect
style="opacity:1;vector-effect:none;fill:#15539e;fill-opacity:1;stroke:#030e1b;stroke-width:1.08532763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal"
id="rect3296"
width="44.446434"
height="20.910645"
x="0.625"
y="291.71494"
rx="10.455324"
ry="10.073335" />
<rect
ry="10.455322"
rx="10.455322"
y="291.71494"
x="24.30357"
height="20.910645"
width="21.142862"
id="rect3300"
style="opacity:1;vector-effect:none;fill:url(#linearGradient3331);fill-opacity:1;stroke:#030e1b;stroke-width:1.08532763;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;marker:none;marker-start:none;marker-mid:none;marker-end:none;paint-order:normal" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

1
data/theme/toggle-on.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="46" height="22"><g transform="translate(0 -291.18)" stroke="#2b73cc"><rect style="marker:none;font-variant-east_asian:normal" width="44.446" height="20.911" x=".625" y="291.715" rx="10.455" ry="10.073" fill="#3081e3"/><rect ry="10.455" rx="10.455" y="291.715" x="24.304" height="20.911" width="21.143" style="marker:none;font-variant-east_asian:normal" fill="#f8f7f7" stroke-linecap="round" stroke-linejoin="round"/></g></svg>

After

Width:  |  Height:  |  Size: 473 B

View File

@ -8,6 +8,8 @@ const Config = imports.misc.config;
const ExtensionUtils = imports.misc.extensionUtils;
const { loadInterfaceXML } = imports.misc.fileUtils;
const { ExtensionState } = ExtensionUtils;
const GnomeShellIface = loadInterfaceXML('org.gnome.Shell.Extensions');
const GnomeShellProxy = Gio.DBusProxy.makeProxyWrapper(GnomeShellIface);
@ -17,74 +19,54 @@ function stripPrefix(string, prefix) {
return string;
}
var Application = class {
constructor() {
var Application = GObject.registerClass({
GTypeName: 'ExtensionPrefs_Application'
}, class Application extends Gtk.Application {
_init() {
GLib.set_prgname('gnome-shell-extension-prefs');
this.application = new Gtk.Application({
super._init({
application_id: 'org.gnome.shell.ExtensionPrefs',
flags: Gio.ApplicationFlags.HANDLES_COMMAND_LINE
});
this.application.connect('activate', this._onActivate.bind(this));
this.application.connect('command-line', this._onCommandLine.bind(this));
this.application.connect('startup', this._onStartup.bind(this));
this._extensionPrefsModules = {};
this._startupUuid = null;
this._loaded = false;
this._skipMainWindow = false;
this._shellProxy = null;
}
_extensionAvailable(uuid) {
let extension = ExtensionUtils.extensions[uuid];
get shellProxy() {
return this._shellProxy;
}
if (!extension)
_showPrefs(uuid) {
let row = this._extensionSelector.get_children().find(c => {
return c.uuid === uuid && c.hasPrefs;
});
if (!row)
return false;
if (!extension.dir.get_child('prefs.js').query_exists(null))
return false;
return true;
}
_getExtensionPrefsModule(extension) {
let uuid = extension.metadata.uuid;
if (this._extensionPrefsModules.hasOwnProperty(uuid))
return this._extensionPrefsModules[uuid];
ExtensionUtils.installImporter(extension);
let prefsModule = extension.imports.prefs;
prefsModule.init(extension.metadata);
this._extensionPrefsModules[uuid] = prefsModule;
return prefsModule;
}
_selectExtension(uuid) {
if (!this._extensionAvailable(uuid))
return;
let extension = ExtensionUtils.extensions[uuid];
let widget;
try {
let prefsModule = this._getExtensionPrefsModule(extension);
widget = prefsModule.buildPrefsWidget();
widget = row.prefsModule.buildPrefsWidget();
} catch (e) {
widget = this._buildErrorUI(extension, e);
widget = this._buildErrorUI(row, e);
}
let dialog = new Gtk.Window({ modal: !this._skipMainWindow,
type_hint: Gdk.WindowTypeHint.DIALOG });
dialog.set_titlebar(new Gtk.HeaderBar({ show_close_button: true,
title: extension.metadata.name,
visible: true }));
let dialog = new Gtk.Window({
modal: !this._skipMainWindow,
type_hint: Gdk.WindowTypeHint.DIALOG
});
dialog.set_titlebar(new Gtk.HeaderBar({
show_close_button: true,
title: row.name,
visible: true
}));
if (this._skipMainWindow) {
this.application.add_window(dialog);
this.add_window(dialog);
if (this._window)
this._window.destroy();
this._window = dialog;
@ -98,7 +80,7 @@ var Application = class {
dialog.show();
}
_buildErrorUI(extension, exc) {
_buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true
@ -168,13 +150,20 @@ var Application = class {
copyButton.connect('clicked', w => {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
let backticks = '```';
clipboard.set_text(
// markdown for pasting in gitlab issues
`The settings of extension ${extension.uuid} had an error:\n${
backticks}\n${exc}\n${backticks}\n\nStack trace:\n${
backticks}\n${exc.stack}${backticks}\n`, -1
);
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${row.uuid} had an error:`,
'```',
`${exc}`,
'```',
'',
'Stack trace:',
'```',
exc.stack.replace(/\n$/, ''), // stack without trailing newline
'```',
''
];
clipboard.set_text(lines.join('\n'), -1);
});
let spacing = new Gtk.SeparatorToolItem({ draw: false });
@ -185,13 +174,13 @@ var Application = class {
label: _("Homepage"),
tooltip_text: _("Visit extension homepage"),
no_show_all: true,
visible: extension.metadata.url != null
visible: row.url != null
});
toolbar.add(urlButton);
urlButton.connect('clicked', w => {
let context = w.get_display().get_app_launch_context();
Gio.AppInfo.launch_default_for_uri(extension.metadata.url, context);
Gio.AppInfo.launch_default_for_uri(row.url, context);
});
let expandedBox = new Gtk.Box({
@ -206,8 +195,8 @@ var Application = class {
return scroll;
}
_buildUI(app) {
this._window = new Gtk.ApplicationWindow({ application: app,
_buildUI() {
this._window = new Gtk.ApplicationWindow({ application: this,
window_position: Gtk.WindowPosition.CENTER });
this._window.set_default_size(800, 500);
@ -241,18 +230,14 @@ var Application = class {
this._mainStack.add_named(new EmptyPlaceholder(), 'placeholder');
this._shellProxy = new GnomeShellProxy(Gio.DBus.session, 'org.gnome.Shell', '/org/gnome/Shell');
this._shellProxy.connectSignal('ExtensionStatusChanged', (proxy, senderName, [uuid, state, error]) => {
if (ExtensionUtils.extensions[uuid] !== undefined)
this._scanExtensions();
});
this._shellProxy.connectSignal('ExtensionStateChanged',
this._onExtensionStateChanged.bind(this));
this._window.show_all();
}
_sortList(row1, row2) {
let name1 = ExtensionUtils.extensions[row1.uuid].metadata.name;
let name2 = ExtensionUtils.extensions[row2.uuid].metadata.name;
return name1.localeCompare(name2);
return row1.name.localeCompare(row2.name);
}
_updateHeader(row, before) {
@ -263,19 +248,55 @@ var Application = class {
row.set_header(sep);
}
_scanExtensions() {
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', this._extensionFound.bind(this));
finder.scanExtensions();
this._extensionsLoaded();
_findExtensionRow(uuid) {
return this._extensionSelector.get_children().find(c => c.uuid === uuid);
}
_extensionFound(finder, extension) {
let row = new ExtensionRow(extension.uuid);
_onExtensionStateChanged(proxy, senderName, [uuid, newState]) {
let row = this._findExtensionRow(uuid);
if (row) {
let { state } = ExtensionUtils.deserializeExtension(newState);
if (state == ExtensionState.UNINSTALLED)
row.destroy();
return; // we only deal with new and deleted extensions here
}
this._shellProxy.GetExtensionInfoRemote(uuid, ([serialized]) => {
let extension = ExtensionUtils.deserializeExtension(serialized);
if (!extension)
return;
// check the extension wasn't added in between
if (this._findExtensionRow(uuid) != null)
return;
this._addExtensionRow(extension);
});
}
_scanExtensions() {
this._shellProxy.ListExtensionsRemote(([extensionsMap], e) => {
if (e) {
if (e instanceof Gio.DBusError) {
log(`Failed to connect to shell proxy: ${e}`);
this._mainStack.add_named(new NoShellPlaceholder(), 'noshell');
this._mainStack.visible_child_name = 'noshell';
} else
throw e;
return;
}
for (let uuid in extensionsMap) {
let extension = ExtensionUtils.deserializeExtension(extensionsMap[uuid]);
this._addExtensionRow(extension);
}
this._extensionsLoaded();
});
}
_addExtensionRow(extension) {
let row = new ExtensionRow(extension);
row.prefsButton.visible = this._extensionAvailable(row.uuid);
row.prefsButton.connect('clicked', () => {
this._selectExtension(row.uuid);
this._showPrefs(row.uuid);
});
row.show_all();
@ -288,24 +309,26 @@ var Application = class {
else
this._mainStack.visible_child_name = 'placeholder';
if (this._startupUuid && this._extensionAvailable(this._startupUuid))
this._selectExtension(this._startupUuid);
if (this._startupUuid)
this._showPrefs(this._startupUuid);
this._startupUuid = null;
this._skipMainWindow = false;
this._loaded = true;
}
_onActivate() {
vfunc_activate() {
this._window.present();
}
_onStartup(app) {
this._buildUI(app);
vfunc_startup() {
super.vfunc_startup();
this._buildUI();
this._scanExtensions();
}
_onCommandLine(app, commandLine) {
app.activate();
vfunc_command_line(commandLine) {
this.activate();
let args = commandLine.get_arguments();
if (args.length) {
@ -316,16 +339,14 @@ var Application = class {
// Strip off "extension:///" prefix which fakes a URI, if it exists
uuid = stripPrefix(uuid, "extension:///");
if (this._extensionAvailable(uuid))
this._selectExtension(uuid);
else if (!this._loaded)
if (!this._loaded)
this._startupUuid = uuid;
else
else if (!this._showPrefs(uuid))
this._skipMainWindow = false;
}
return 0;
}
};
});
var Expander = GObject.registerClass({
Properties: {
@ -492,6 +513,35 @@ class EmptyPlaceholder extends Gtk.Box {
}
});
var NoShellPlaceholder = GObject.registerClass(
class NoShellPlaceholder extends Gtk.Box {
_init() {
super._init({
orientation: Gtk.Orientation.VERTICAL,
spacing: 12,
margin: 100,
margin_bottom: 60
});
let label = new Gtk.Label({
label: '<span size="x-large">%s</span>'.format(
_("Somethings gone wrong")),
use_markup: true
});
label.get_style_context().add_class(Gtk.STYLE_CLASS_DIM_LABEL);
this.add(label);
label = new Gtk.Label({
label: _("Were very sorry, but it was not possible to get the list of installed extensions. Make sure you are logged into GNOME and try again."),
justify: Gtk.Justification.CENTER,
wrap: true
});
this.add(label);
this.show_all();
}
});
var DescriptionLabel = GObject.registerClass(
class DescriptionLabel extends Gtk.Label {
vfunc_get_preferred_height_for_width(width) {
@ -504,30 +554,55 @@ class DescriptionLabel extends Gtk.Label {
var ExtensionRow = GObject.registerClass(
class ExtensionRow extends Gtk.ListBoxRow {
_init(uuid) {
_init(extension) {
super._init();
this.uuid = uuid;
this._app = Gio.Application.get_default();
this._extension = extension;
this._prefsModule = null;
this._settings = new Gio.Settings({ schema_id: 'org.gnome.shell' });
this._settings.connect('changed::enabled-extensions', () => {
this._switch.state = this._isEnabled();
});
this._settings.connect('changed::disable-extension-version-validation',
() => {
this._switch.sensitive = this._canEnable();
});
this._settings.connect('changed::disable-user-extensions',
() => {
this._switch.sensitive = this._canEnable();
this._extensionStateChangedId = this._app.shellProxy.connectSignal(
'ExtensionStateChanged', (p, sender, [uuid, newState]) => {
if (this.uuid !== uuid)
return;
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = (this._extension.state == ExtensionState.ENABLED);
this._switch.state = state;
this._switch.sensitive = this._canToggle();
});
this.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
}
_buildUI() {
let extension = ExtensionUtils.extensions[this.uuid];
get uuid() {
return this._extension.uuid;
}
get name() {
return this._extension.metadata.name;
}
get hasPrefs() {
return this._extension.hasPrefs;
}
get url() {
return this._extension.metadata.url;
}
_onDestroy() {
if (!this._app.shellProxy)
return;
if (this._extensionStateChangedId)
this._app.shellProxy.disconnectSignal(this._extensionStateChangedId);
this._extensionStateChangedId = 0;
}
_buildUI() {
let hbox = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL,
hexpand: true, margin_end: 24, spacing: 24,
margin: 12 });
@ -537,19 +612,20 @@ class ExtensionRow extends Gtk.ListBoxRow {
spacing: 6, hexpand: true });
hbox.add(vbox);
let name = GLib.markup_escape_text(extension.metadata.name, -1);
let name = GLib.markup_escape_text(this.name, -1);
let label = new Gtk.Label({ label: '<b>' + name + '</b>',
use_markup: true,
halign: Gtk.Align.START });
vbox.add(label);
let desc = extension.metadata.description.split('\n')[0];
let desc = this._extension.metadata.description.split('\n')[0];
label = new DescriptionLabel({ label: desc, wrap: true, lines: 2,
ellipsize: Pango.EllipsizeMode.END,
xalign: 0, yalign: 0 });
vbox.add(label);
let button = new Gtk.Button({ valign: Gtk.Align.CENTER,
visible: this.hasPrefs,
no_show_all: true });
button.set_image(new Gtk.Image({ icon_name: 'emblem-system-symbolic',
icon_size: Gtk.IconSize.BUTTON,
@ -559,51 +635,37 @@ class ExtensionRow extends Gtk.ListBoxRow {
this.prefsButton = button;
this._switch = new Gtk.Switch({ valign: Gtk.Align.CENTER,
sensitive: this._canEnable(),
state: this._isEnabled() });
this._switch = new Gtk.Switch({
valign: Gtk.Align.CENTER,
sensitive: this._canToggle(),
state: this._extension.state === ExtensionState.ENABLED
});
this._switch.connect('notify::active', () => {
if (this._switch.active)
this._enable();
this._app.shellProxy.EnableExtensionRemote(this.uuid);
else
this._disable();
this._app.shellProxy.DisableExtensionRemote(this.uuid);
});
this._switch.connect('state-set', () => true);
hbox.add(this._switch);
}
_canEnable() {
let extension = ExtensionUtils.extensions[this.uuid];
let checkVersion = !this._settings.get_boolean('disable-extension-version-validation');
return !this._settings.get_boolean('disable-user-extensions') &&
!(checkVersion && ExtensionUtils.isOutOfDate(extension));
_canToggle() {
return this._extension.canChange;
}
_isEnabled() {
let extensions = this._settings.get_strv('enabled-extensions');
return extensions.indexOf(this.uuid) != -1;
}
get prefsModule() {
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
_enable() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.indexOf(this.uuid) != -1)
return;
// give extension prefs access to their own extension object
ExtensionUtils.getCurrentExtension = () => this._extension;
extensions.push(this.uuid);
this._settings.set_strv('enabled-extensions', extensions);
}
this._prefsModule = this._extension.imports.prefs;
this._prefsModule.init(this._extension.metadata);
}
_disable() {
let extensions = this._settings.get_strv('enabled-extensions');
let pos = extensions.indexOf(this.uuid);
if (pos == -1)
return;
do {
extensions.splice(pos, 1);
pos = extensions.indexOf(this.uuid);
} while (pos != -1);
this._settings.set_strv('enabled-extensions', extensions);
return this._prefsModule;
}
});
@ -611,12 +673,12 @@ function initEnvironment() {
// Monkey-patch in a "global" object that fakes some Shell utilities
// that ExtensionUtils depends on.
window.global = {
log() {
print([].join.call(arguments, ', '));
log(...args) {
print(args.join(', '));
},
logError(s) {
log('ERROR: ' + s);
log(`ERROR: ${s}`);
},
userdatadir: GLib.build_filenamev([GLib.get_user_data_dir(), 'gnome-shell'])
@ -631,6 +693,5 @@ function main(argv) {
Gettext.bindtextdomain(Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
Gettext.textdomain(Config.GETTEXT_PACKAGE);
let app = new Application();
app.application.run(argv);
new Application().run(argv);
}

View File

@ -59,23 +59,23 @@ var AuthPrompt = class {
this.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('next', () => {
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.updateSensitivity(false);
this.startSpinning();
if (this._queryingService) {
this._userVerifier.answerQuery(this._queryingService, this._entry.text);
} else {
this._preemptiveAnswer = this._entry.text;
}
});
this.actor = new St.BoxLayout({ style_class: 'login-dialog-prompt-layout',
vertical: true });
this.actor.connect('destroy', this._onDestroy.bind(this));
this.actor.connect('key-press-event', (actor, event) => {
if (event.get_key_symbol() == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
});
if (event.get_key_symbol() == Clutter.KEY_Escape)
this.cancel();
return Clutter.EVENT_PROPAGATE;
});
this._userWell = new St.Bin({ x_fill: true,
x_align: St.Align.START });
@ -112,7 +112,7 @@ var AuthPrompt = class {
this._buttonBox = new St.BoxLayout({ style_class: 'login-dialog-button-box',
vertical: false });
this.actor.add(this._buttonBox,
{ expand: true,
{ expand: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.END });
@ -138,7 +138,7 @@ var AuthPrompt = class {
reactive: true,
can_focus: true,
label: _("Cancel") });
this.cancelButton.connect('clicked', () => { this.cancel(); });
this.cancelButton.connect('clicked', () => this.cancel());
this._buttonBox.add(this.cancelButton,
{ expand: false,
x_fill: false,
@ -157,7 +157,7 @@ var AuthPrompt = class {
reactive: true,
can_focus: true,
label: _("Next") });
this.nextButton.connect('clicked', () => { this.emit('next'); });
this.nextButton.connect('clicked', () => this.emit('next'));
this.nextButton.add_style_pseudo_class('default');
this._buttonBox.add(this.nextButton,
{ expand: false,
@ -295,12 +295,11 @@ var AuthPrompt = class {
time: DEFAULT_BUTTON_WELL_ANIMATION_TIME,
delay: DEFAULT_BUTTON_WELL_ANIMATION_DELAY,
transition: 'linear',
onCompleteScope: this,
onComplete() {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
onComplete: () => {
if (wasSpinner) {
if (this._spinner)
this._spinner.stop();
}
}
});
}

View File

@ -44,6 +44,7 @@
* replaced by something else.
*/
const { GObject } = imports.gi;
const Signals = imports.signals;
var Task = class {
@ -176,36 +177,36 @@ Signals.addSignalMethods(Batch.prototype);
var ConcurrentBatch = class extends Batch {
process() {
let hold = this.runTask();
let hold = this.runTask();
if (hold) {
this.hold.acquireUntilAfter(hold);
}
if (hold) {
this.hold.acquireUntilAfter(hold);
}
// Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run
// concurrently.
this.nextTask();
// Regardless of the state of the just run task,
// fire off the next one, so all the tasks can run
// concurrently.
this.nextTask();
}
};
Signals.addSignalMethods(ConcurrentBatch.prototype);
var ConsecutiveBatch = class extends Batch {
process() {
let hold = this.runTask();
let hold = this.runTask();
if (hold && hold.isAcquired()) {
// This task is inhibiting the batch. Wait on it
// before processing the next one.
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();
}
if (hold && hold.isAcquired()) {
// This task is inhibiting the batch. Wait on it
// before processing the next one.
let signalId = hold.connect('release', () => {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();
}
}
};
Signals.addSignalMethods(ConsecutiveBatch.prototype);

View File

@ -23,8 +23,8 @@ function FprintManager() {
try {
self.init(null);
} catch(e) {
log('Failed to connect to Fprint service: ' + e.message);
} catch (e) {
log(`Failed to connect to Fprint service: ${e.message}`);
return null;
}

View File

@ -43,7 +43,7 @@ var UserListItem = class {
constructor(user) {
this.user = user;
this._userChangedId = this.user.connect('changed',
this._onUserChanged.bind(this));
this._onUserChanged.bind(this));
let layout = new St.BoxLayout({ vertical: true });
this.actor = new St.Button({ style_class: 'login-dialog-user-list-item',
@ -150,7 +150,7 @@ Signals.addSignalMethods(UserListItem.prototype);
var UserList = class {
constructor() {
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view'});
this.actor = new St.ScrollView({ style_class: 'login-dialog-user-list-view' });
this.actor.set_policy(St.PolicyType.NEVER,
St.PolicyType.AUTOMATIC);
@ -187,8 +187,6 @@ var UserList = class {
}
updateStyle(isExpanded) {
let tasks = [];
if (isExpanded)
this._box.add_style_pseudo_class('expanded');
else
@ -244,7 +242,7 @@ var UserList = class {
return;
if (user.locked)
return;
return;
let userName = user.get_user_name();
@ -261,7 +259,7 @@ var UserList = class {
item.connect('activate', this._onItemActivated.bind(this));
// Try to keep the focused item front-and-center
item.actor.connect('key-focus-in', () => { this.scrollToItem(item); });
item.actor.connect('key-focus-in', () => this.scrollToItem(item));
this._moveFocusToItems();
@ -319,17 +317,17 @@ var SessionMenuButton = class {
this._menu.actor.hide();
this._menu.connect('open-state-changed', (menu, isOpen) => {
if (isOpen)
this._button.add_style_pseudo_class('active');
else
this._button.remove_style_pseudo_class('active');
if (isOpen)
this._button.add_style_pseudo_class('active');
else
this._button.remove_style_pseudo_class('active');
});
this._manager = new PopupMenu.PopupMenuManager(this._button,
{ actionMode: Shell.ActionMode.NONE });
this._manager.addMenu(this._menu);
this._button.connect('clicked', () => { this._menu.toggle(); });
this._button.connect('clicked', () => this._menu.toggle());
this._items = {};
this._activeSessionId = null;
@ -353,11 +351,11 @@ var SessionMenuButton = class {
}
setActiveSession(sessionId) {
if (sessionId == this._activeSessionId)
return;
if (sessionId == this._activeSessionId)
return;
this._activeSessionId = sessionId;
this._updateOrnament();
this._activeSessionId = sessionId;
this._updateOrnament();
}
close() {
@ -403,18 +401,18 @@ var LoginDialog = GObject.registerClass({
this.connect('destroy', this._onDestroy.bind(this));
parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default()
this._userManager = AccountsService.UserManager.get_default();
this._gdmClient = new Gdm.Client();
this._settings = new Gio.Settings({ schema_id: GdmUtil.LOGIN_SCREEN_SCHEMA });
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_KEY,
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_KEY}`,
this._updateBanner.bind(this));
this._settings.connect('changed::' + GdmUtil.BANNER_MESSAGE_TEXT_KEY,
this._settings.connect(`changed::${GdmUtil.BANNER_MESSAGE_TEXT_KEY}`,
this._updateBanner.bind(this));
this._settings.connect('changed::' + GdmUtil.DISABLE_USER_LIST_KEY,
this._settings.connect(`changed::${GdmUtil.DISABLE_USER_LIST_KEY}`,
this._updateDisableUserList.bind(this));
this._settings.connect('changed::' + GdmUtil.LOGO_KEY,
this._settings.connect(`changed::${GdmUtil.LOGO_KEY}`,
this._updateLogo.bind(this));
this._textureCache = St.TextureCache.get_default();
@ -575,19 +573,15 @@ var LoginDialog = GObject.registerClass({
// First find out what space the children require
let bannerAllocation = null;
let bannerHeight = 0;
let bannerWidth = 0;
if (this._bannerView.visible) {
bannerAllocation = this._getBannerAllocation(dialogBox, this._bannerView);
bannerHeight = bannerAllocation.y2 - bannerAllocation.y1;
bannerWidth = bannerAllocation.x2 - bannerAllocation.x1;
}
let authPromptAllocation = null;
let authPromptHeight = 0;
let authPromptWidth = 0;
if (this._authPrompt.actor.visible) {
authPromptAllocation = this._getCenterActorAllocation(dialogBox, this._authPrompt.actor);
authPromptHeight = authPromptAllocation.y2 - authPromptAllocation.y1;
authPromptWidth = authPromptAllocation.x2 - authPromptAllocation.x1;
}
@ -619,64 +613,64 @@ var LoginDialog = GObject.registerClass({
let leftOverYSpace = bannerSpace - bannerHeight;
if (leftOverYSpace > 0) {
// First figure out how much left over space is up top
let leftOverTopSpace = leftOverYSpace / 2;
// First figure out how much left over space is up top
let leftOverTopSpace = leftOverYSpace / 2;
// Then, shift the banner into the middle of that extra space
let yShift = Math.floor(leftOverTopSpace / 2);
// Then, shift the banner into the middle of that extra space
let yShift = Math.floor(leftOverTopSpace / 2);
bannerAllocation.y1 += yShift;
bannerAllocation.y2 += yShift;
bannerAllocation.y1 += yShift;
bannerAllocation.y2 += yShift;
} else {
// Then figure out how much space there would be if we switched to a
// wide layout with banner on one side and authprompt on the other.
let leftOverXSpace = dialogWidth - authPromptWidth;
// Then figure out how much space there would be if we switched to a
// wide layout with banner on one side and authprompt on the other.
let leftOverXSpace = dialogWidth - authPromptWidth;
// In a wide view, half of the available space goes to the banner,
// and the other half goes to the margins.
let wideBannerWidth = leftOverXSpace / 2;
let wideSpacing = leftOverXSpace - wideBannerWidth;
// In a wide view, half of the available space goes to the banner,
// and the other half goes to the margins.
let wideBannerWidth = leftOverXSpace / 2;
let wideSpacing = leftOverXSpace - wideBannerWidth;
// If we do go with a wide layout, we need there to be at least enough
// space for the banner and the auth prompt to be the same width,
// so it doesn't look unbalanced.
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
let centerX = dialogBox.x1 + dialogWidth / 2;
let centerY = dialogBox.y1 + dialogHeight / 2;
// If we do go with a wide layout, we need there to be at least enough
// space for the banner and the auth prompt to be the same width,
// so it doesn't look unbalanced.
if (authPromptWidth > 0 && wideBannerWidth > authPromptWidth) {
let centerX = dialogBox.x1 + dialogWidth / 2;
let centerY = dialogBox.y1 + dialogHeight / 2;
// A small portion of the spacing goes down the center of the
// screen to help delimit the two columns of the wide view
let centerGap = wideSpacing / 8;
// A small portion of the spacing goes down the center of the
// screen to help delimit the two columns of the wide view
let centerGap = wideSpacing / 8;
// place the banner along the left edge of the center margin
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// place the banner along the left edge of the center margin
bannerAllocation.x2 = Math.floor(centerX - centerGap / 2);
bannerAllocation.x1 = Math.floor(bannerAllocation.x2 - wideBannerWidth);
// figure out how tall it would like to be and try to accommodate
// but don't let it get too close to the logo
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
// figure out how tall it would like to be and try to accommodate
// but don't let it get too close to the logo
let [wideMinHeight, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
bannerAllocation.y1 = Math.floor(centerY - wideBannerHeight / 2);
bannerAllocation.y2 = bannerAllocation.y1 + wideBannerHeight;
// place the auth prompt along the right edge of the center margin
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
} else {
// If we aren't going to do a wide view, then we need to limit
// the height of the banner so it will present scrollbars
// place the auth prompt along the right edge of the center margin
authPromptAllocation.x1 = Math.floor(centerX + centerGap / 2);
authPromptAllocation.x2 = authPromptAllocation.x1 + authPromptWidth;
} else {
// If we aren't going to do a wide view, then we need to limit
// the height of the banner so it will present scrollbars
// First figure out how much space there is without the banner
leftOverYSpace += bannerHeight;
// First figure out how much space there is without the banner
leftOverYSpace += bannerHeight;
// Then figure out how much of that space is up top
let availableTopSpace = Math.floor(leftOverYSpace / 2);
// Then figure out how much of that space is up top
let availableTopSpace = Math.floor(leftOverYSpace / 2);
// Then give all of that space to the banner
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
}
// Then give all of that space to the banner
bannerAllocation.y2 = bannerAllocation.y1 + availableTopSpace;
}
}
} else if (userSelectionAllocation) {
// Grow the user list to fill the space
@ -851,10 +845,10 @@ var LoginDialog = GObject.registerClass({
_shouldShowSessionMenuButton() {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFYING &&
this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.VERIFICATION_FAILED)
return false;
return false;
if (this._user && this._user.is_loaded && this._user.is_logged_in())
return false;
return false;
return true;
}
@ -919,7 +913,7 @@ var LoginDialog = GObject.registerClass({
{ opacity: 255,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
onUpdate: () => {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
@ -927,12 +921,10 @@ var LoginDialog = GObject.registerClass({
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
onComplete() {
onComplete: () => {
if (this._authPrompt.verificationStatus != AuthPrompt.AuthPromptStatus.NOT_VERIFYING)
this._authPrompt.reset();
},
onCompleteScope: this });
} });
}
_gotGreeterSessionProxy(proxy) {
@ -949,7 +941,7 @@ var LoginDialog = GObject.registerClass({
{ opacity: 0,
time: _FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
onUpdate: () => {
let children = Main.layoutManager.uiGroup.get_children();
for (let i = 0; i < children.length; i++) {
@ -957,22 +949,20 @@ var LoginDialog = GObject.registerClass({
children[i].opacity = this.opacity;
}
},
onUpdateScope: this,
onComplete() {
onComplete: () => {
this._greeter.call_start_session_when_ready_sync(serviceName, true, null);
},
onCompleteScope: this });
} });
}
_onSessionOpened(client, serviceName) {
this._authPrompt.finish(() => { this._startSession(serviceName); });
this._authPrompt.finish(() => this._startSession(serviceName));
}
_waitForItemForUser(userName) {
let item = this._userList.getItemFromUserName(userName);
if (item)
return null;
return null;
let hold = new Batch.Hold();
let signalId = this._userList.connect('item-added',
@ -983,7 +973,7 @@ var LoginDialog = GObject.registerClass({
hold.release();
});
hold.connect('release', () => { this._userList.disconnect(signalId); });
hold.connect('release', () => this._userList.disconnect(signalId));
return hold;
}
@ -1047,6 +1037,7 @@ var LoginDialog = GObject.registerClass({
return this._blockTimedLoginUntilIdle();
} else {
animationTime = delay;
return null;
}
},
@ -1082,12 +1073,12 @@ var LoginDialog = GObject.registerClass({
// Restart timed login on user interaction
global.stage.connect('captured-event', (actor, event) => {
if (event.type() == Clutter.EventType.KEY_PRESS ||
if (event.type() == Clutter.EventType.KEY_PRESS ||
event.type() == Clutter.EventType.BUTTON_PRESS) {
this._startTimedLogin(userName, seconds);
}
this._startTimedLogin(userName, seconds);
}
return Clutter.EVENT_PROPAGATE;
return Clutter.EVENT_PROPAGATE;
});
}

View File

@ -19,7 +19,7 @@ var Manager = class {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
this._reloadRealms.bind(this))
this._reloadRealms.bind(this));
this._realms = {};
this._signalId = this._aggregateProvider.connect('g-properties-changed',
@ -36,10 +36,10 @@ var Manager = class {
return;
for (let i = 0; i < realmPaths.length; i++) {
let realm = Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
this._onRealmLoaded.bind(this));
Realm(Gio.DBus.system,
'org.freedesktop.realmd',
realmPaths[i],
this._onRealmLoaded.bind(this));
}
}
@ -98,10 +98,10 @@ var Manager = class {
Service(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',
service => { service.ReleaseRemote(); });
service => service.ReleaseRemote());
this._aggregateProvider.disconnect(this._signalId);
this._realms = { };
this._updateLoginFormat();
}
};
Signals.addSignalMethods(Manager.prototype)
Signals.addSignalMethods(Manager.prototype);

View File

@ -30,7 +30,7 @@ var LOGO_KEY = 'logo';
var DISABLE_USER_LIST_KEY = 'disable-user-list';
// Give user 48ms to read each character of a PAM message
var USER_READ_TIME = 48
var USER_READ_TIME = 48;
var MessageType = {
NONE: 0,
@ -342,7 +342,7 @@ var ShellUserVerifier = class {
try {
this._clearUserVerifier();
this._userVerifier = client.open_reauthentication_channel_finish(result);
} catch(e) {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
@ -369,7 +369,7 @@ var ShellUserVerifier = class {
try {
this._clearUserVerifier();
this._userVerifier = client.get_user_verifier_finish(result);
} catch(e) {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to obtain user verifier', e);
@ -423,36 +423,31 @@ var ShellUserVerifier = class {
_startService(serviceName) {
this._hold.acquire();
if (this._userName) {
this._userVerifier.call_begin_verification_for_user(serviceName,
this._userName,
this._cancellable,
(obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._userVerifier.call_begin_verification_for_user(serviceName, this._userName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_for_user_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification for user', e);
return;
}
this._hold.release();
});
this._hold.release();
});
} else {
this._userVerifier.call_begin_verification(serviceName,
this._cancellable,
(obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch(e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._userVerifier.call_begin_verification(serviceName, this._cancellable, (obj, result) => {
try {
obj.call_begin_verification_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
this._reportInitError('Failed to start verification', e);
return;
}
this._hold.release();
});
this._hold.release();
});
}
}

View File

@ -64,6 +64,7 @@
<file>ui/keyboard.js</file>
<file>ui/layout.js</file>
<file>ui/lightbox.js</file>
<file>ui/locatePointer.js</file>
<file>ui/lookingGlass.js</file>
<file>ui/magnifier.js</file>
<file>ui/magnifierDBus.js</file>
@ -81,9 +82,11 @@
<file>ui/pageIndicators.js</file>
<file>ui/panel.js</file>
<file>ui/panelMenu.js</file>
<file>ui/pointerA11yTimeout.js</file>
<file>ui/pointerWatcher.js</file>
<file>ui/popupMenu.js</file>
<file>ui/remoteSearch.js</file>
<file>ui/ripples.js</file>
<file>ui/runDialog.js</file>
<file>ui/screenShield.js</file>
<file>ui/screencast.js</file>
@ -120,6 +123,7 @@
<file>ui/status/accessibility.js</file>
<file>ui/status/brightness.js</file>
<file>ui/status/dwellClick.js</file>
<file>ui/status/location.js</file>
<file>ui/status/keyboard.js</file>
<file>ui/status/nightLight.js</file>

View File

@ -3,21 +3,32 @@
// Common utils for the extension system and the extension
// preferences tool
const Gettext = imports.gettext;
const Signals = imports.signals;
const { Gio, GLib } = imports.gi;
const Gio = imports.gi.Gio;
const Gettext = imports.gettext;
const Lang = imports.lang;
const Config = imports.misc.config;
const FileUtils = imports.misc.fileUtils;
var ExtensionType = {
SYSTEM: 1,
PER_USER: 2
};
// Maps uuid -> metadata object
var extensions = {};
var ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99
};
const SERIALIZED_PROPERTIES = ['type', 'state', 'path', 'error', 'hasPrefs', 'canChange'];
/**
* getCurrentExtension:
@ -31,7 +42,7 @@ function getCurrentExtension() {
// Search for an occurrence of an extension stack frame
// Start at 1 because 0 is the stack frame of this function
for (let i = 1; i < stack.length; i++) {
if (stack[i].indexOf('/gnome-shell/extensions/') > -1) {
if (stack[i].includes('/gnome-shell/extensions/')) {
extensionStackLine = stack[i];
break;
}
@ -49,13 +60,17 @@ function getCurrentExtension() {
if (!match)
return null;
// local import, as the module is used from outside the gnome-shell process
// as well (not this function though)
let extensionManager = imports.ui.main.extensionManager;
let path = match[1];
let file = Gio.File.new_for_path(path);
// Walk up the directory tree, looking for an extension with
// the same UUID as a directory name.
while (file != null) {
let extension = extensions[file.get_basename()];
let extension = extensionManager.lookup(file.get_basename());
if (extension !== undefined)
return extension;
file = file.get_parent();
@ -161,54 +176,50 @@ function isOutOfDate(extension) {
return false;
}
function createExtensionObject(uuid, dir, type) {
let info;
function serializeExtension(extension) {
let obj = {};
Lang.copyProperties(extension.metadata, obj);
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
SERIALIZED_PROPERTIES.forEach(prop => {
obj[prop] = extension[prop];
});
let metadataContents, success, tag;
try {
[success, metadataContents, tag] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) {
throw new Error('Failed to load metadata.json: ' + e);
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error('Failed to parse metadata.json: ' + e);
}
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i];
if (!meta[prop]) {
throw new Error('missing "' + prop + '" property in metadata.json');
let res = {};
for (let key in obj) {
let val = obj[key];
let type;
switch (typeof val) {
case 'string':
type = 's';
break;
case 'number':
type = 'd';
break;
case 'boolean':
type = 'b';
break;
default:
continue;
}
res[key] = GLib.Variant.new(type, val);
}
if (uuid != meta.uuid) {
throw new Error('uuid "' + meta.uuid + '" from metadata.json does not match directory name "' + uuid + '"');
return res;
}
function deserializeExtension(variant) {
let res = { metadata: {} };
for (let prop in variant) {
let val = variant[prop].unpack();
if (SERIALIZED_PROPERTIES.includes(prop))
res[prop] = val;
else
res.metadata[prop] = val;
}
let extension = {};
extension.metadata = meta;
extension.uuid = meta.uuid;
extension.type = type;
extension.dir = dir;
extension.path = dir.get_path();
extension.error = '';
extension.hasPrefs = dir.get_child('prefs.js').query_exists(null);
extensions[uuid] = extension;
return extension;
// add the 2 additional properties to create a valid extension object, as createExtensionObject()
res.uuid = res.metadata.uuid;
res.dir = Gio.File.new_for_path(res.path);
return res;
}
function installImporter(extension) {
@ -219,36 +230,3 @@ function installImporter(extension) {
extension.imports = imports[extension.uuid];
imports.searchPath = oldSearchPath;
}
var ExtensionFinder = class {
_loadExtension(extensionDir, info, perUserDir) {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = extensions[uuid];
if (existing) {
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, extensionDir.get_path()));
return;
}
let extension;
let type = extensionDir.has_prefix(perUserDir) ? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = createExtensionObject(uuid, extensionDir, type);
} catch(e) {
logError(e, 'Could not load extension %s'.format(uuid));
return;
}
this.emit('extension-found', extension);
}
scanExtensions() {
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
this._loadExtension(dir, info, perUserDir);
});
}
};
Signals.addSignalMethods(ExtensionFinder.prototype);

View File

@ -36,7 +36,7 @@ function recursivelyDeleteDir(dir, deleteParent) {
let children = dir.enumerate_children('standard::name,standard::type',
Gio.FileQueryInfoFlags.NONE, null);
let info, child;
let info;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let child = dir.get_child(info.get_name());
@ -57,7 +57,7 @@ function recursivelyMoveDir(srcDir, destDir) {
if (!destDir.query_exists(null))
destDir.make_directory_with_parents(null);
let info, child;
let info;
while ((info = children.next_file(null)) != null) {
let type = info.get_file_type();
let srcChild = srcDir.get_child(info.get_name());
@ -86,11 +86,11 @@ function loadInterfaceXML(iface) {
try {
let [ok, bytes] = f.load_contents(null);
if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes)
xml = imports.byteArray.toString(bytes);
else
xml = bytes.toString();
} catch (e) {
log('Failed to load D-Bus interface ' + iface);
log(`Failed to load D-Bus interface ${iface}`);
}
return xml;

View File

@ -18,7 +18,7 @@ var HistoryManager = class {
this._historyIndex = 0;
if (this._key) {
this._history = global.settings.get_strv(this._key);
global.settings.connect('changed::' + this._key,
global.settings.connect(`changed::${this._key}`,
this._historyChanged.bind(this));
} else {
@ -66,7 +66,7 @@ var HistoryManager = class {
this._indexChanged();
}
return this._historyIndex ? this._history[this._historyIndex -1] : null;
return this._historyIndex ? this._history[this._historyIndex - 1] : null;
}
addItem(input) {

View File

@ -42,7 +42,7 @@ var IBusManager = class {
this._candidatePopup = new IBusCandidatePopup.CandidatePopup();
this._panelService = null;
this._engines = {};
this._engines = new Map();
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
@ -62,8 +62,8 @@ var IBusManager = class {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
} catch(e) {
log('Failed to launch ibus-daemon: ' + e.message);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
}
}
@ -73,7 +73,7 @@ var IBusManager = class {
this._panelService = null;
this._candidatePopup.setPanelService(null);
this._engines = {};
this._engines.clear();
this._ready = false;
this._registerPropertiesId = 0;
this._currentEngineName = null;
@ -96,7 +96,7 @@ var IBusManager = class {
if (enginesList) {
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines[name] = enginesList[i];
this._engines.set(name, enginesList[i]);
}
this._updateReadiness();
} else {
@ -119,7 +119,7 @@ var IBusManager = class {
if (!GLib.str_has_suffix(path, '/InputContext_1'))
this.emit ('focus-in');
});
this._panelService.connect('focus-out', () => { this.emit('focus-out'); });
this._panelService.connect('focus-out', () => this.emit('focus-out'));
try {
// IBus versions older than 1.5.10 have a bug which
@ -138,7 +138,7 @@ var IBusManager = class {
engine = this._ibus.get_global_engine_async_finish(result);
if (!engine)
return;
} catch(e) {
} catch (e) {
return;
}
this._engineChanged(this._ibus, engine.get_name());
@ -150,8 +150,7 @@ var IBusManager = class {
}
_updateReadiness() {
this._ready = (Object.keys(this._engines).length > 0 &&
this._panelService != null);
this._ready = this._engines.size > 0 && this._panelService != null;
this.emit('ready', this._ready);
}
@ -189,10 +188,10 @@ var IBusManager = class {
}
getEngineDesc(id) {
if (!this._ready || !this._engines.hasOwnProperty(id))
if (!this._ready || !this._engines.has(id))
return null;
return this._engines[id];
return this._engines.get(id);
}
setEngine(id, callback) {

View File

@ -74,7 +74,7 @@ class InputMethod extends Clutter.InputMethod {
this._context = null;
this._hints = 0;
this._purpose = 0;
this._preeditStr = ''
this._preeditStr = '';
this._preeditPos = 0;
this._preeditVisible = false;
}
@ -262,7 +262,7 @@ class InputMethod extends Clutter.InputMethod {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);
} catch (e) {
log('Error processing key on IM: ' + e.message);
log(`Error processing key on IM: ${e.message}`);
}
});
return true;

View File

@ -46,11 +46,11 @@ var IntrospectService = class {
}
_isIntrospectEnabled() {
return this._settings.get_boolean(INTROSPECT_KEY);
return this._settings.get_boolean(INTROSPECT_KEY);
}
_isSenderWhitelisted(sender) {
return APP_WHITELIST.includes(sender);
return APP_WHITELIST.includes(sender);
}
_getSandboxedAppId(app) {

View File

@ -51,14 +51,14 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// if we encounter anything that isn't a letter, '.', ')', or ']',
// we should stop parsing.
function isStopChar(c) {
return !c.match(/[\w\.\)\]]/);
return !c.match(/[\w.)\]]/);
}
// Given the ending position of a quoted string, find where it starts
function findMatchingQuote(expr, offset) {
let quoteChar = expr.charAt(offset);
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == quoteChar && expr.charAt(i-1) != '\\'){
if (expr.charAt(i) == quoteChar && expr.charAt(i - 1) != '\\') {
return i;
}
}
@ -68,7 +68,7 @@ function findMatchingQuote(expr, offset) {
// Given the ending position of a regex, find where it starts
function findMatchingSlash(expr, offset) {
for (let i = offset - 1; i >= 0; --i) {
if (expr.charAt(i) == '/' && expr.charAt(i-1) != '\\'){
if (expr.charAt(i) == '/' && expr.charAt(i - 1) != '\\') {
return i;
}
}
@ -81,7 +81,7 @@ function findMatchingSlash(expr, offset) {
// findMatchingBrace("[(])", 3) returns 1.
function findMatchingBrace(expr, offset) {
let closeBrace = expr.charAt(offset);
let openBrace = ({')': '(', ']': '['})[closeBrace];
let openBrace = ({ ')': '(', ']': '[' })[closeBrace];
function findTheBrace(expr, offset) {
if (offset < 0) {
@ -117,11 +117,11 @@ function getExpressionOffset(expr, offset) {
while (offset >= 0) {
let currChar = expr.charAt(offset);
if (isStopChar(currChar)){
if (isStopChar(currChar)) {
return offset + 1;
}
if (currChar.match(/[\)\]]/)) {
if (currChar.match(/[)\]]/)) {
offset = findMatchingBrace(expr, offset);
}
@ -151,15 +151,11 @@ function getAllProps(obj) {
// e.g., expr="({ foo: null, bar: null, 4: null })" will
// return ["foo", "bar", ...] but the list will not include "4",
// since methods accessed with '.' notation must star with a letter or _.
function getPropertyNamesFromExpression(expr, commandHeader) {
if (commandHeader == null) {
commandHeader = '';
}
function getPropertyNamesFromExpression(expr, commandHeader = '') {
let obj = {};
if (!isUnsafeExpression(expr)) {
try {
obj = eval(commandHeader + expr);
obj = eval(commandHeader + expr);
} catch (e) {
return [];
}
@ -168,7 +164,7 @@ function getPropertyNamesFromExpression(expr, commandHeader) {
}
let propsUnique = {};
if (typeof obj === 'object'){
if (typeof obj === 'object') {
let allProps = getAllProps(obj);
// Get only things we are allowed to complete following a '.'
allProps = allProps.filter( isValidPropertyName );

View File

@ -60,7 +60,7 @@ var KeyboardManager = class {
this._currentKeymap.options == options)
return;
this._currentKeymap = {layouts, variants, options};
this._currentKeymap = { layouts, variants, options };
Meta.get_backend().set_keymap(layouts, variants, options);
}
@ -125,7 +125,7 @@ var KeyboardManager = class {
_getLocaleLayout() {
let locale = GLib.get_language_names()[0];
if (locale.indexOf('_') == -1)
if (!locale.includes('_'))
locale = DEFAULT_LOCALE;
let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);

View File

@ -43,11 +43,33 @@ function canLock() {
let version = result.deep_unpack()[0].deep_unpack();
return haveSystemd() && versionCompare('3.5.91', version);
} catch(e) {
} catch (e) {
return false;
}
}
function registerSessionWithGDM() {
log("Registering session with GDM");
Gio.DBus.system.call('org.gnome.DisplayManager',
'/org/gnome/DisplayManager/Manager',
'org.gnome.DisplayManager.Manager',
'RegisterSession',
GLib.Variant.new('(a{sv})', [{}]), null,
Gio.DBusCallFlags.NONE, -1, null,
(source, result) => {
try {
source.call_finish(result);
} catch (e) {
if (!e.matches(Gio.DBusError, Gio.DBusError.UNKNOWN_METHOD))
log(`Error registering session with GDM: ${e.message}`);
else
log("Not calling RegisterSession(): method not exported, GDM too old?");
}
}
);
}
let _loginManager = null;
/**
@ -163,7 +185,7 @@ var LoginManagerSystemd = class {
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd: fd }));
} catch(e) {
} catch (e) {
logError(e, "Error getting systemd inhibitor");
callback(null);
}

View File

@ -26,33 +26,33 @@ function _getMobileProvidersDatabase() {
}
// _findProviderForMccMnc:
// @operator_name: operator name
// @operator_code: operator code
// @operatorName: operator name
// @operatorCode: operator code
//
// Given an operator name string (which may not be a real operator name) and an
// operator code string, tries to find a proper operator name to display.
//
function _findProviderForMccMnc(operator_name, operator_code) {
if (operator_name) {
if (operator_name.length != 0 &&
(operator_name.length > 6 || operator_name.length < 5)) {
function _findProviderForMccMnc(operatorName, operatorCode) {
if (operatorName) {
if (operatorName.length != 0 &&
(operatorName.length > 6 || operatorName.length < 5)) {
// this looks like a valid name, i.e. not an MCCMNC (that some
// devices return when not yet connected
return operator_name;
return operatorName;
}
if (isNaN(parseInt(operator_name))) {
if (isNaN(parseInt(operatorName))) {
// name is definitely not a MCCMNC, so it may be a name
// after all; return that
return operator_name;
return operatorName;
}
}
let needle;
if ((!operator_name || operator_name.length == 0) && operator_code)
needle = operator_code;
else if (operator_name && (operator_name.length == 6 || operator_name.length == 5))
needle = operator_name;
if ((!operatorName || operatorName.length == 0) && operatorCode)
needle = operatorCode;
else if (operatorName && (operatorName.length == 6 || operatorName.length == 5))
needle = operatorName;
else // nothing to search
return null;
@ -71,7 +71,7 @@ function _findProviderForMccMnc(operator_name, operator_code) {
// Tries to find the operator name corresponding to the given SID
//
function _findProviderForSid(sid) {
if (sid == 0)
if (!sid)
return null;
let mpd = _getMobileProvidersDatabase();
@ -173,7 +173,7 @@ var ModemCdma = class {
} else {
let [bandClass, band, sid] = result;
this.operator_name = _findProviderForSid(sid)
this.operator_name = _findProviderForSid(sid);
}
this.emit('notify::operator-name');
});
@ -230,17 +230,17 @@ var BroadbandModem = class {
}
_reloadOperatorName() {
let new_name = "";
let newName = "";
if (this.operator_name_3gpp && this.operator_name_3gpp.length > 0)
new_name += this.operator_name_3gpp;
newName += this.operator_name_3gpp;
if (this.operator_name_cdma && this.operator_name_cdma.length > 0) {
if (new_name != "")
new_name += ", ";
new_name += this.operator_name_cdma;
if (newName != "")
newName += ", ";
newName += this.operator_name_cdma;
}
this.operator_name = new_name;
this.operator_name = newName;
this.emit('notify::operator-name');
}

View File

@ -77,54 +77,51 @@ var ObjectManager = class {
let info = this._interfaceInfos[interfaceName];
if (!info) {
if (onFinished)
onFinished();
return;
if (onFinished)
onFinished();
return;
}
let proxy = new Gio.DBusProxy({ g_connection: this._connection,
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
g_name: this._serviceName,
g_object_path: objectPath,
g_interface_name: interfaceName,
g_interface_info: info,
g_flags: Gio.DBusProxyFlags.DO_NOT_AUTO_START });
proxy.init_async(GLib.PRIORITY_DEFAULT,
this._cancellable,
(initable, result) => {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize proxy for interface ' + interfaceName);
proxy.init_async(GLib.PRIORITY_DEFAULT, this._cancellable, (initable, result) => {
try {
initable.init_finish(result);
} catch (e) {
logError(e, `could not initialize proxy for interface ${interfaceName}`);
if (onFinished)
onFinished();
return;
}
if (onFinished)
onFinished();
return;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
let isNewObject;
if (!this._objects[objectPath]) {
this._objects[objectPath] = {};
isNewObject = true;
} else {
isNewObject = false;
}
this._objects[objectPath][interfaceName] = proxy;
this._objects[objectPath][interfaceName] = proxy;
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
if (!this._interfaces[interfaceName])
this._interfaces[interfaceName] = [];
this._interfaces[interfaceName].push(proxy);
this._interfaces[interfaceName].push(proxy);
if (isNewObject)
this.emit('object-added', objectPath);
if (isNewObject)
this.emit('object-added', objectPath);
this.emit('interface-added', interfaceName, proxy);
this.emit('interface-added', interfaceName, proxy);
if (onFinished)
onFinished();
if (onFinished)
onFinished();
});
}
@ -155,11 +152,10 @@ var ObjectManager = class {
}
_onManagerProxyLoaded(initable, result) {
let error = null;
try {
initable.init_finish(result);
} catch(e) {
logError(e, 'could not initialize object manager for object ' + this._serviceName);
} catch (e) {
logError(e, `could not initialize object manager for object ${this._serviceName}`);
this._tryToCompleteLoad();
return;
@ -197,7 +193,7 @@ var ObjectManager = class {
this._managerProxy.GetManagedObjectsRemote((result, error) => {
if (!result) {
if (error) {
logError(error, 'could not get remote objects for service ' + this._serviceName + ' path ' + this._managerPath);
logError(error, `could not get remote objects for service ${this._serviceName} path ${this._managerPath}`);
}
this._tryToCompleteLoad();

View File

@ -14,22 +14,13 @@
//
// Return value: a new object, containing the merged parameters from
// @params and @defaults
function parse(params, defaults, allowExtras) {
let ret = {}, prop;
if (!params)
params = {};
for (prop in params) {
if (!(prop in defaults) && !allowExtras)
throw new Error('Unrecognized parameter "' + prop + '"');
ret[prop] = params[prop];
function parse(params = {}, defaults, allowExtras) {
if (!allowExtras) {
for (let prop in params)
if (!(prop in defaults))
throw new Error(`Unrecognized parameter "${prop}"`);
}
for (prop in defaults) {
if (!(prop in params))
ret[prop] = defaults[prop];
}
return ret;
}
let defaultsCopy = Object.assign({}, defaults);
return Object.assign(defaultsCopy, params);
}

View File

@ -12,4 +12,4 @@ function PermissionStore(initCallback, cancellable) {
'org.freedesktop.impl.portal.PermissionStore',
'/org/freedesktop/impl/portal/PermissionStore',
initCallback, cancellable);
};
}

View File

@ -29,7 +29,7 @@ var SmartcardManager = class {
this._objectManager = new ObjectManager.ObjectManager({ connection: Gio.DBus.session,
name: "org.gnome.SettingsDaemon.Smartcard",
objectPath: '/org/gnome/SettingsDaemon/Smartcard',
knownInterfaces: [ SmartcardTokenIface ],
knownInterfaces: [SmartcardTokenIface],
onLoaded: this._onLoaded.bind(this) });
this._insertedTokens = {};
this._loginToken = null;

View File

@ -83,48 +83,54 @@ const SystemActions = GObject.registerClass({
this._canHaveSuspend = true;
this._actions = new Map();
this._actions.set(POWER_OFF_ACTION_ID,
{ // Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown;reboot;restart").split(/[; ]/),
available: false });
this._actions.set(LOCK_SCREEN_ACTION_ID,
{ // Translators: The name of the lock screen action in search
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/),
available: false });
this._actions.set(LOGOUT_ACTION_ID,
{ // Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false });
this._actions.set(SUSPEND_ACTION_ID,
{ // Translators: The name of the suspend action in search
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
available: false });
this._actions.set(SWITCH_USER_ACTION_ID,
{ // Translators: The name of the switch user action in search
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/),
available: false });
this._actions.set(LOCK_ORIENTATION_ACTION_ID,
{ // Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock Orientation"),
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
available: false });
this._actions.set(POWER_OFF_ACTION_ID, {
// Translators: The name of the power-off action in search
name: C_("search-result", "Power Off"),
iconName: 'system-shutdown-symbolic',
// Translators: A list of keywords that match the power-off action, separated by semicolons
keywords: _("power off;shutdown;reboot;restart").split(/[; ]/),
available: false
});
this._actions.set(LOCK_SCREEN_ACTION_ID, {
// Translators: The name of the lock screen action in search
name: C_("search-result", "Lock Screen"),
iconName: 'system-lock-screen-symbolic',
// Translators: A list of keywords that match the lock screen action, separated by semicolons
keywords: _("lock screen").split(/[; ]/),
available: false
});
this._actions.set(LOGOUT_ACTION_ID, {
// Translators: The name of the logout action in search
name: C_("search-result", "Log Out"),
iconName: 'application-exit-symbolic',
// Translators: A list of keywords that match the logout action, separated by semicolons
keywords: _("logout;log out;sign off").split(/[; ]/),
available: false
});
this._actions.set(SUSPEND_ACTION_ID, {
// Translators: The name of the suspend action in search
name: C_("search-result", "Suspend"),
iconName: 'media-playback-pause-symbolic',
// Translators: A list of keywords that match the suspend action, separated by semicolons
keywords: _("suspend;sleep").split(/[; ]/),
available: false
});
this._actions.set(SWITCH_USER_ACTION_ID, {
// Translators: The name of the switch user action in search
name: C_("search-result", "Switch User"),
iconName: 'system-switch-user-symbolic',
// Translators: A list of keywords that match the switch user action, separated by semicolons
keywords: _("switch user").split(/[; ]/),
available: false
});
this._actions.set(LOCK_ORIENTATION_ACTION_ID, {
// Translators: The name of the lock orientation action in search
name: C_("search-result", "Lock Orientation"),
iconName: '',
// Translators: A list of keywords that match the lock orientation action, separated by semicolons
keywords: _("lock orientation;screen;rotation").split(/[; ]/),
available: false
});
this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA });
this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
@ -137,37 +143,39 @@ const SystemActions = GObject.registerClass({
this._userManager = AccountsService.UserManager.get_default();
this._userManager.connect('notify::is-loaded',
() => { this._updateMultiUser(); });
() => this._updateMultiUser());
this._userManager.connect('notify::has-multiple-users',
() => { this._updateMultiUser(); });
() => this._updateMultiUser());
this._userManager.connect('user-added',
() => { this._updateMultiUser(); });
() => this._updateMultiUser());
this._userManager.connect('user-removed',
() => { this._updateMultiUser(); });
() => this._updateMultiUser());
this._lockdownSettings.connect('changed::' + DISABLE_USER_SWITCH_KEY,
() => { this._updateSwitchUser(); });
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => { this._updateLogout(); });
global.settings.connect('changed::' + ALWAYS_SHOW_LOG_OUT_KEY,
() => { this._updateLogout(); });
this._lockdownSettings.connect(`changed::${DISABLE_USER_SWITCH_KEY}`,
() => this._updateSwitchUser());
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
() => this._updateLogout());
global.settings.connect(`changed::${ALWAYS_SHOW_LOG_OUT_KEY}`,
() => this._updateLogout());
this._lockdownSettings.connect('changed::' + DISABLE_LOCK_SCREEN_KEY,
() => { this._updateLockScreen(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOCK_SCREEN_KEY}`,
() => this._updateLockScreen());
this._lockdownSettings.connect('changed::' + DISABLE_LOG_OUT_KEY,
() => { this._updateHaveShutdown(); });
this._lockdownSettings.connect(`changed::${DISABLE_LOG_OUT_KEY}`,
() => this._updateHaveShutdown());
this.forceUpdate();
this._orientationSettings.connect('changed::orientation-lock',
() => { this._updateOrientationLock();
this._updateOrientationLockIcon(); });
() => {
this._updateOrientationLock();
this._updateOrientationLockIcon();
});
Main.layoutManager.connect('monitors-changed',
() => { this._updateOrientationLock(); });
() => this._updateOrientationLock());
Gio.DBus.system.watch_name(SENSOR_BUS_NAME,
Gio.BusNameWatcherFlags.NONE,
() => { this._sensorProxyAppeared(); },
() => this._sensorProxyAppeared(),
() => {
this._sensorProxy = null;
this._updateOrientationLock();
@ -175,7 +183,7 @@ const SystemActions = GObject.registerClass({
this._updateOrientationLock();
this._updateOrientationLockIcon();
Main.sessionMode.connect('updated', () => { this._sessionUpdated(); });
Main.sessionMode.connect('updated', () => this._sessionUpdated());
this._sessionUpdated();
}
@ -215,7 +223,7 @@ const SystemActions = GObject.registerClass({
return;
}
this._sensorProxy.connect('g-properties-changed',
() => { this._updateOrientationLock(); });
() => this._updateOrientationLock());
this._updateOrientationLock();
});
}
@ -257,11 +265,11 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map((term) => { return term.toLowerCase(); });
terms = terms.map((term) => term.toLowerCase());
let results = [];
for (let [key, {available, keywords}] of this._actions)
for (let [key, { available, keywords }] of this._actions)
if (available && terms.every(t => keywords.some(k => k.startsWith(t))))
results.push(key);
@ -278,24 +286,24 @@ const SystemActions = GObject.registerClass({
activateAction(id) {
switch (id) {
case POWER_OFF_ACTION_ID:
this.activatePowerOff();
break;
case LOCK_SCREEN_ACTION_ID:
this.activateLockScreen();
break;
case LOGOUT_ACTION_ID:
this.activateLogout();
break;
case SUSPEND_ACTION_ID:
this.activateSuspend();
break;
case SWITCH_USER_ACTION_ID:
this.activateSwitchUser();
break;
case LOCK_ORIENTATION_ACTION_ID:
this.activateLockOrientation();
break;
case POWER_OFF_ACTION_ID:
this.activatePowerOff();
break;
case LOCK_SCREEN_ACTION_ID:
this.activateLockScreen();
break;
case LOGOUT_ACTION_ID:
this.activateLogout();
break;
case SUSPEND_ACTION_ID:
this.activateSuspend();
break;
case SWITCH_USER_ACTION_ID:
this.activateSwitchUser();
break;
case LOCK_ORIENTATION_ACTION_ID:
this.activateLockOrientation();
break;
}
}

View File

@ -17,7 +17,7 @@ const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _urlRegexp = new RegExp(
'(^|' + _leadingJunk + ')' +
`(^|${_leadingJunk})` +
'(' +
'(?:' +
'(?:http|https|ftp)://' + // scheme://
@ -29,12 +29,12 @@ const _urlRegexp = new RegExp(
'(?:' + // one or more:
'[^\\s()<>]+' + // run of non-space non-()
'|' + // or
_balancedParens + // balanced parens
`${_balancedParens}` + // balanced parens
')+' +
'(?:' + // end with:
_balancedParens + // balanced parens
`${_balancedParens}` + // balanced parens
'|' + // or
_notTrailingJunk + // last non-junk char
`${_notTrailingJunk}` + // last non-junk char
')' +
')', 'gi');
@ -69,16 +69,16 @@ function spawn(argv) {
}
// spawnCommandLine:
// @command_line: a command line
// @commandLine: a command line
//
// Runs @command_line in the background, handling any errors that
// Runs @commandLine in the background, handling any errors that
// occur when trying to parse or start the program.
function spawnCommandLine(command_line) {
function spawnCommandLine(commandLine) {
try {
let [success, argv] = GLib.shell_parse_argv(command_line);
let [success, argv] = GLib.shell_parse_argv(commandLine);
trySpawn(argv);
} catch (err) {
_handleSpawnError(command_line, err);
_handleSpawnError(commandLine, err);
}
}
@ -93,7 +93,7 @@ function spawnApp(argv) {
let context = global.create_app_launch_context(0, -1);
app.launch([], context);
} catch(err) {
} catch (err) {
_handleSpawnError(argv[0], err);
}
}
@ -103,8 +103,7 @@ function spawnApp(argv) {
//
// Runs @argv in the background. If launching @argv fails,
// this will throw an error.
function trySpawn(argv)
{
function trySpawn(argv) {
var success, pid;
try {
[success, pid] = GLib.spawn_async(null, argv, null,
@ -135,19 +134,19 @@ function trySpawn(argv)
}
// trySpawnCommandLine:
// @command_line: a command line
// @commandLine: a command line
//
// Runs @command_line in the background. If launching @command_line
// Runs @commandLine in the background. If launching @commandLine
// fails, this will throw an error.
function trySpawnCommandLine(command_line) {
function trySpawnCommandLine(commandLine) {
let success, argv;
try {
[success, argv] = GLib.shell_parse_argv(command_line);
[success, argv] = GLib.shell_parse_argv(commandLine);
} catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer
err.message = err.message.replace(/[^:]*: /, _("Could not parse command:") + "\n");
err.message = err.message.replace(/[^:]*: /, `${_("Could not parse command:")}\n`);
throw err;
}
@ -222,7 +221,7 @@ function formatTime(time, params) {
/* Translators: Time in 24h format */
format = N_("%H\u2236%M");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo <2)
else if (daysAgo < 2)
/* Translators: this is the word "Yesterday" followed by a
time string in 24h format. i.e. "Yesterday, 14:30" */
// xgettext:no-c-format
@ -251,7 +250,7 @@ function formatTime(time, params) {
/* Translators: Time in 12h format */
format = N_("%l\u2236%M %p");
// Show the word "Yesterday" and time if date is on yesterday
else if (daysAgo <2)
else if (daysAgo < 2)
/* Translators: this is the word "Yesterday" followed by a
time string in 12h format. i.e. "Yesterday, 2:30 pm" */
// xgettext:no-c-format
@ -289,7 +288,7 @@ function createTimeLabel(date, params) {
let id = _desktopSettings.connect('changed::clock-format', () => {
label.text = formatTime(date, params);
});
label.connect('destroy', () => { _desktopSettings.disconnect(id); });
label.connect('destroy', () => _desktopSettings.disconnect(id));
return label;
}
@ -346,7 +345,7 @@ function insertSorted(array, val, cmp) {
var CloseButton = GObject.registerClass(
class CloseButton extends St.Button {
_init(boxpointer) {
super._init({ style_class: 'notification-close'});
super._init({ style_class: 'notification-close' });
// This is a bit tricky. St.Bin has its own x-align/y-align properties
// that compete with Clutter's properties. This should be fixed for
@ -380,7 +379,7 @@ class CloseButton extends St.Button {
let themeNode = this.get_theme_node();
let offY = this._computeBoxPointerOffset();
this.translation_x = themeNode.get_length('-shell-close-overlap-x')
this.translation_x = themeNode.get_length('-shell-close-overlap-x');
this.translation_y = themeNode.get_length('-shell-close-overlap-y') + offY;
}
@ -467,7 +466,7 @@ var AppSettingsMonitor = class {
if (!this._settings || handler.id > 0)
return;
handler.id = this._settings.connect('changed::' + handler.key,
handler.id = this._settings.connect(`changed::${handler.key}`,
handler.callback);
handler.callback(this._settings, handler.key);
}
@ -493,13 +492,13 @@ var AppSettingsMonitor = class {
}
_setSettings(settings) {
this._handlers.forEach((handler) => { this._disconnectHandler(handler); });
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); });
this._handlers.forEach((handler) => this._connectHandler(handler));
if (hadSettings != haveSettings)
this.emit('available-changed');

View File

@ -26,7 +26,7 @@ var WeatherClient = class {
this._weatherAuthorized = false;
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) {
log('Failed to connect to permissionStore: ' + error.message);
log(`Failed to connect to permissionStore: ${error.message}`);
return;
}
@ -40,7 +40,7 @@ var WeatherClient = class {
this._permStore.LookupRemote('gnome', 'geolocation', (res, error) => {
if (error)
log('Error looking up permission: ' + error.message);
log(`Error looking up permission: ${error.message}`);
let [perms, data] = error ? [{}, null] : res;
let params = ['gnome', 'geolocation', false, data, perms];
@ -68,7 +68,7 @@ var WeatherClient = class {
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
'org.gnome.Weather');
this._weatherAppMon.connect('available-changed', () => { this.emit('changed'); });
this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
this._weatherAppMon.watchSetting('automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations',
@ -178,8 +178,8 @@ var WeatherClient = class {
(o, res) => {
try {
this._gclueService = Geoclue.Simple.new_finish(res);
} catch(e) {
log('Failed to connect to Geoclue2 service: ' + e.message);
} catch (e) {
log(`Failed to connect to Geoclue2 service: ${e.message}`);
this._setLocation(this._mostRecentLocation);
return;
}

View File

@ -19,7 +19,7 @@ var METRICS = {
units: "frames / s" },
overviewLatencySubsequent:
{ description: "Time to first frame after triggering overview, second time",
units: "us"},
units: "us" },
overviewFpsSubsequent:
{ description: "Frames rate when going to the overview, second time",
units: "frames / s" },
@ -52,7 +52,7 @@ var METRICS = {
units: "us" },
applicationsShowTimeSubsequent:
{ description: "Time to switch to applications view, second time",
units: "us"}
units: "us" }
};
let WINDOW_CONFIGS = [
@ -136,7 +136,6 @@ let overviewFrames;
let overviewLatency;
let mallocUsedSize = 0;
let overviewShowCount = 0;
let firstOverviewUsedSize;
let haveSwapComplete = false;
let applicationsShowStart;
let applicationsShowCount = 0;

View File

@ -30,7 +30,7 @@ var METRICS = {
geditStartTime:
{ description: "Time from gedit launch to window drawn",
units: "us" },
}
};
function waitAndDraw(milliseconds) {
let cb;
@ -48,7 +48,7 @@ function waitAndDraw(milliseconds) {
cb();
});
return callback => { cb = callback; };
return callback => cb = callback;
}
function waitSignal(object, signal) {
@ -60,7 +60,7 @@ function waitSignal(object, signal) {
cb();
});
return callback => { cb = callback; };
return callback => cb = callback;
}
function extractBootTimestamp() {
@ -157,7 +157,7 @@ function *run() {
Main.overview.hide();
yield Scripting.createTestWindow({ maximized: true,
redraws: true});
redraws: true });
yield Scripting.waitTestWindows();
yield Scripting.sleep(1000);
@ -269,11 +269,11 @@ function script_collectTimings(time) {
if (len == 0)
median = -1;
else if (len % 2 == 1)
median = times[(len - 1)/ 2];
median = times[(len - 1) / 2];
else
median = Math.round((times[len / 2 - 1] + times[len / 2]) / 2);
METRICS[timing + 'RedrawTime'].value = median;
METRICS[`${timing}RedrawTime`].value = median;
}
}

View File

@ -19,7 +19,6 @@ const PortalHelperSecurityLevel = {
INSECURE: 2
};
const INACTIVITY_TIMEOUT = 30000; //ms
const CONNECTIVITY_CHECK_HOST = 'nmcheck.gnome.org';
const CONNECTIVITY_CHECK_URI = 'http://' + CONNECTIVITY_CHECK_HOST;
const CONNECTIVITY_RECHECK_RATELIMIT_TIMEOUT = 30 * GLib.USEC_PER_SEC;
@ -59,7 +58,7 @@ class PortalHeaderBar extends Gtk.HeaderBar {
single_line_mode: true,
ellipsize: Pango.EllipsizeMode.END,
valign: Gtk.Align.BASELINE,
selectable: true});
selectable: true });
this.subtitleLabel.get_style_context().add_class('subtitle');
hbox.add(this.subtitleLabel);
@ -265,7 +264,7 @@ class WebPortalHelper extends Gtk.Application {
this._queue = [];
let action = new Gio.SimpleAction({ name: 'quit' });
action.connect('activate', () => { this.active_window.destroyWindow(); });
action.connect('activate', () => this.active_window.destroyWindow());
this.add_action(action);
}

View File

@ -1,4 +1,4 @@
const { Clutter, Gio, GLib, Shell } = imports.gi;
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi;
const CheckBox = imports.ui.checkBox;
const Dialog = imports.ui.dialog;
@ -15,9 +15,10 @@ var DialogResponse = {
CLOSED: 2
};
var AccessDialog = class extends ModalDialog.ModalDialog {
constructor(invocation, handle, title, subtitle, body, options) {
super({ styleClass: 'access-dialog' });
var AccessDialog = GObject.registerClass(
class AccessDialog extends ModalDialog.ModalDialog {
_init(invocation, handle, title, subtitle, body, options) {
super._init({ styleClass: 'access-dialog' });
this._invocation = invocation;
this._handle = handle;
@ -68,7 +69,7 @@ var AccessDialog = class extends ModalDialog.ModalDialog {
this.addButton({ label: grantLabel,
action: () => {
this._sendResponse(DialogResponse.OK);
}});
} });
}
open() {
@ -109,7 +110,7 @@ var AccessDialog = class extends ModalDialog.ModalDialog {
});
this.close();
}
};
});
var AccessDialogDBus = class {
constructor() {
@ -134,7 +135,7 @@ var AccessDialogDBus = class {
let [handle, appId, parentWindow, title, subtitle, body, options] = params;
// We probably want to use parentWindow and global.display.focus_window
// for this check in the future
if (appId && appId + '.desktop' != this._windowTracker.focus_app.id) {
if (appId && `${appId}.desktop` != this._windowTracker.focus_app.id) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'Only the focused app is allowed to show a system access dialog');
@ -145,7 +146,7 @@ var AccessDialogDBus = class {
subtitle, body, options);
dialog.open();
dialog.connect('closed', () => { this._accessDialog = null; });
dialog.connect('closed', () => this._accessDialog = null);
this._accessDialog = dialog;
}

View File

@ -36,7 +36,7 @@ function _createWindowClone(window, size) {
// usual hack for the usual bug in ClutterBinLayout...
x_expand: true,
y_expand: true });
};
}
function getWindows(workspace) {
// We ignore skip-taskbar windows in switchers, but if they are attached
@ -395,7 +395,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
{ opacity: 255,
time: THUMBNAIL_FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => { this.thumbnailsVisible = true; }
onComplete: () => this.thumbnailsVisible = true
});
this._switcherList._items[this._selectedIndex].add_accessible_state (Atk.StateType.EXPANDED);
@ -459,7 +459,7 @@ class CyclerHighlight {
_onDestroy() {
this.window = null;
}
};
}
// We don't show an actual popup, so just provide what SwitcherPopup
// expects instead of inheriting from SwitcherList
@ -663,14 +663,6 @@ class AppIcon extends St.BoxLayout {
set_size(size) {
this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon;
this._iconBin.set_size(size, size);
}
vfunc_get_preferred_width(forHeight) {
let [minWidth, ] = super.vfunc_get_preferred_width(forHeight);
minWidth = Math.max(minWidth, forHeight);
return [minWidth, minWidth];
}
});
@ -724,15 +716,16 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_setIconSize() {
let j = 0;
while(this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++;
while (this._items.length > 1 && this._items[j].style_class != 'item-box') {
j++;
}
let themeNode = this._items[j].get_theme_node();
this._list.ensure_style();
let iconPadding = themeNode.get_horizontal_padding();
let iconBorder = themeNode.get_border_width(St.Side.LEFT) + themeNode.get_border_width(St.Side.RIGHT);
let [iconMinHeight, iconNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = iconNaturalHeight + iconPadding + iconBorder;
let [, labelNaturalHeight] = this.icons[j].label.get_preferred_height(-1);
let iconSpacing = labelNaturalHeight + iconPadding + iconBorder;
let totalSpacing = this._list.spacing * (this._items.length - 1);
// We just assume the whole screen here due to weirdness happing with the passed width
@ -745,7 +738,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
let iconSize = baseIconSizes[0];
if (this._items.length > 1) {
for(let i = 0; i < baseIconSizes.length; i++) {
for (let i = 0; i < baseIconSizes.length; i++) {
iconSize = baseIconSizes[i];
let height = iconSizes[i] + iconSpacing;
let w = height * this._items.length + totalSpacing;
@ -756,7 +749,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._iconSize = iconSize;
for(let i = 0; i < this.icons.length; i++) {
for (let i = 0; i < this.icons.length; i++) {
if (this.icons[i].icon != null)
break;
this.icons[i].set_size(iconSize);
@ -802,8 +795,9 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else
this._itemEntered(index);
} else {
this._itemEntered(index);
}
}
_enterItem(index) {
@ -848,9 +842,8 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
this._removeIcon(app);
});
let n = this._arrows.length;
let arrow = new St.DrawingArea({ style_class: 'switcher-arrow' });
arrow.connect('repaint', () => { SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM); });
arrow.connect('repaint', () => SwitcherPopup.drawArrow(arrow, St.Side.BOTTOM));
this.add_actor(arrow);
this._arrows.push(arrow);
@ -991,23 +984,23 @@ class WindowIcon extends St.BoxLayout {
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
switch (mode) {
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
break;
case AppIconMode.THUMBNAIL_ONLY:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
break;
case AppIconMode.BOTH:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
case AppIconMode.BOTH:
size = WINDOW_PREVIEW_SIZE;
this._icon.add_actor(_createWindowClone(mutterWindow, size * scaleFactor));
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL));
break;
if (this.app)
this._icon.add_actor(this._createAppIcon(this.app,
APP_ICON_SIZE_SMALL));
break;
case AppIconMode.APP_ICON_ONLY:
size = APP_ICON_SIZE;
this._icon.add_actor(this._createAppIcon(this.app, size));
case AppIconMode.APP_ICON_ONLY:
size = APP_ICON_SIZE;
this._icon.add_actor(this._createAppIcon(this.app, size));
}
this._icon.set_size(size * scaleFactor, size * scaleFactor);
@ -1044,7 +1037,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
this._removeWindow(window)
this._removeWindow(window);
});
}
@ -1080,7 +1073,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
childBox.y1 = childBox.y2 - this._label.height;
this._label.allocate(childBox, flags);
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM)
let totalLabelHeight = this._label.height + themeNode.get_padding(St.Side.BOTTOM);
childBox.x1 = box.x1;
childBox.x2 = box.x2;
childBox.y1 = box.y1;

View File

@ -62,11 +62,11 @@ var Animation = class {
if (!validResourceScale)
return;
let texture_cache = St.TextureCache.get_default();
let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._animations = texture_cache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this._animations = textureCache.load_sliced_image(file, width, height,
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
}
@ -123,7 +123,7 @@ var AnimatedIcon = class extends Animation {
};
var Spinner = class extends AnimatedIcon {
constructor(size, animate=false) {
constructor(size, animate = false) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size);
@ -162,7 +162,7 @@ var Spinner = class extends AnimatedIcon {
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => {
this.stop(false);
super.stop();
}
});
} else {

View File

@ -20,7 +20,6 @@ const SystemActions = imports.misc.systemActions;
const { loadInterfaceXML } = imports.misc.fileUtils;
var MAX_APPLICATION_WORK_MILLIS = 75;
var MENU_POPUP_TIMEOUT = 600;
var MAX_COLUMNS = 6;
var MIN_COLUMNS = 4;
@ -34,23 +33,9 @@ var FOLDER_SUBICON_FRACTION = .4;
var MIN_FREQUENT_APPS_COUNT = 3;
var INDICATORS_BASE_TIME = 0.25;
var INDICATORS_ANIMATION_DELAY = 0.125;
var INDICATORS_ANIMATION_MAX_TIME = 0.75;
var VIEWS_SWITCH_TIME = 0.4;
var VIEWS_SWITCH_ANIMATION_DELAY = 0.1;
// Follow iconGrid animations approach and divide by 2 to animate out to
// not annoy the user when the user wants to quit appDisplay.
// Also, make sure we don't exceed iconGrid animation total time or
// views switch time.
var INDICATORS_BASE_TIME_OUT = 0.125;
var INDICATORS_ANIMATION_DELAY_OUT = 0.0625;
var INDICATORS_ANIMATION_MAX_TIME_OUT =
Math.min (VIEWS_SWITCH_TIME,
IconGrid.ANIMATION_TIME_OUT + IconGrid.ANIMATION_MAX_DELAY_OUT_FOR_ITEM);
var PAGE_SWITCH_TIME = 0.3;
const SWITCHEROO_BUS_NAME = 'net.hadess.SwitcherooControl';
@ -69,7 +54,7 @@ function _getCategories(info) {
function _listsIntersect(a, b) {
for (let itemA of a)
if (b.indexOf(itemA) >= 0)
if (b.includes(itemA))
return true;
return false;
}
@ -84,7 +69,7 @@ function _getFolderName(folder) {
try {
keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
} catch(e) {
} catch (e) {
return name;
}
}
@ -109,7 +94,7 @@ class BaseAppView {
padWithSpacing: true });
params = Params.parse(params, { usePagination: false });
if(params.usePagination)
if (params.usePagination)
this._grid = new IconGrid.PaginatedIconGrid(gridParams);
else
this._grid = new IconGrid.IconGrid(gridParams);
@ -158,7 +143,7 @@ class BaseAppView {
loadGrid() {
this._allItems.sort(this._compareItems);
this._allItems.forEach(item => { this._grid.addItem(item); });
this._allItems.forEach(item => this._grid.addItem(item));
this.emit('view-loaded');
}
@ -166,7 +151,7 @@ class BaseAppView {
if (this._items[id])
this._items[id].actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
else
log('No such application ' + id);
log(`No such application ${id}`);
}
selectApp(id) {
@ -227,12 +212,12 @@ class BaseAppView {
} else {
params.opacity = 0;
params.delay = 0;
params.onComplete = () => { this.actor.hide(); };
params.onComplete = () => this.actor.hide();
}
Tweener.addTween(this._grid, params);
}
};
}
Signals.addSignalMethods(BaseAppView.prototype);
var AllView = class AllView extends BaseAppView {
@ -246,7 +231,7 @@ var AllView = class AllView extends BaseAppView {
reactive: true,
y_align: St.Align.START });
this.actor = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand:true, y_expand:true });
x_expand: true, y_expand: true });
this.actor.add_actor(this._scrollView);
this._scrollView.set_policy(St.PolicyType.NEVER,
@ -300,7 +285,7 @@ var AllView = class AllView extends BaseAppView {
this._availWidth = 0;
this._availHeight = 0;
Main.overview.connect('hidden', () => { this.goToPage(0); });
Main.overview.connect('hidden', () => this.goToPage(0));
this._grid.connect('space-opened', () => {
let fadeEffect = this._scrollView.get_effect('fade');
if (fadeEffect)
@ -373,8 +358,8 @@ var AllView = class AllView extends BaseAppView {
_loadApps() {
this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
try {
let id = appInfo.get_id(); // catch invalid file encodings
} catch(e) {
(appInfo.get_id()); // catch invalid file encodings
} catch (e) {
return false;
}
return appInfo.should_show();
@ -447,7 +432,7 @@ var AllView = class AllView extends BaseAppView {
transition: 'easeOutQuad',
opacity: 0,
onComplete() {
this.opacity = 255;
this.opacity = 255;
} });
if (animationDirection == IconGrid.AnimationDirection.OUT)
@ -546,7 +531,7 @@ var AllView = class AllView extends BaseAppView {
}
_onPanEnd(action) {
if (this._displayingPopup)
if (this._displayingPopup)
return;
let pageHeight = this._grid.getPageHeight();
@ -585,7 +570,7 @@ var AllView = class AllView extends BaseAppView {
this._eventBlocker.reactive = isOpen;
this._currentPopup = isOpen ? popup : null;
this._updateIconOpacities(isOpen);
if(!isOpen)
if (!isOpen)
this._closeSpaceForPopup();
});
}
@ -632,9 +617,9 @@ var AllView = class AllView extends BaseAppView {
this._scrollView.get_effect('fade').fade_edges = true;
if (this._availWidth != availWidth || this._availHeight != availHeight || oldNPages != this._grid.nPages()) {
this._adjustment.value = 0;
this._grid.currentPage = 0;
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._adjustment.value = 0;
this._grid.currentPage = 0;
this._pageIndicators.setNPages(this._grid.nPages());
this._pageIndicators.setCurrentPage(0);
});
@ -686,7 +671,7 @@ var FrequentView = class FrequentView extends BaseAppView {
let mostUsed = this._usage.get_most_used();
let hasUsefulData = this.hasUsefulData();
this._noFrequentAppsLabel.visible = !hasUsefulData;
if(!hasUsefulData)
if (!hasUsefulData)
return;
// Allow dragging of the icon only if the Dash would accept a drop to
@ -735,11 +720,11 @@ class ControlsBoxLayout extends Clutter.BoxLayout {
let maxMinWidth = 0;
let maxNaturalWidth = 0;
for (let child = container.get_first_child();
child;
child = child.get_next_sibling()) {
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
maxMinWidth = Math.max(maxMinWidth, minWidth);
maxNaturalWidth = Math.max(maxNaturalWidth, natWidth);
child;
child = child.get_next_sibling()) {
let [minWidth, natWidth] = child.get_preferred_width(forHeight);
maxMinWidth = Math.max(maxMinWidth, minWidth);
maxNaturalWidth = Math.max(maxNaturalWidth, natWidth);
}
let childrenCount = container.get_n_children();
let totalSpacing = this.spacing * (childrenCount - 1);
@ -802,7 +787,7 @@ var AppDisplay = class AppDisplay {
// shown next, so make sure to restore their opacity
// when they are hidden
if (this._controls.mapped)
return;
return;
Tweener.removeTweens(this._controls);
this._controls.opacity = 255;
@ -867,14 +852,14 @@ var AppDisplay = class AppDisplay {
this._controls.opacity = 0;
finalOpacity = 255;
} else {
finalOpacity = 0
finalOpacity = 0;
}
Tweener.addTween(this._controls,
{ time: IconGrid.ANIMATION_TIME_IN,
transition: 'easeInOutQuad',
opacity: finalOpacity,
});
});
currentView.animate(animationDirection, onComplete);
}
@ -910,7 +895,7 @@ var AppDisplay = class AppDisplay {
_onAllocatedSizeChanged(actor, width, height) {
let box = new Clutter.ActorBox();
box.x1 = box.y1 =0;
box.x1 = box.y1 = 0;
box.x2 = width;
box.y2 = height;
box = this._viewStack.get_theme_node().get_content_box(box);
@ -941,7 +926,7 @@ var AppSearchProvider = class AppSearchProvider {
'name': app.get_name(),
'createIcon'(size) {
return app.create_icon_texture(size);
}
}
});
} else {
let name = this._systemActions.getName(id);
@ -1165,7 +1150,7 @@ var FolderIcon = class FolderIcon {
let excludedApps = this._folder.get_strv('excluded-apps');
let appSys = Shell.AppSystem.get_default();
let addAppId = appId => {
if (excludedApps.indexOf(appId) >= 0)
if (excludedApps.includes(appId))
return;
let app = appSys.lookup_app(appId);
@ -1266,7 +1251,7 @@ var FolderIcon = class FolderIcon {
adaptToSize(width, height) {
this._parentAvailableWidth = width;
this._parentAvailableHeight = height;
if(this._popup)
if (this._popup)
this.view.adaptToSize(width, height);
this._popupInvalidated = true;
}
@ -1314,7 +1299,7 @@ var AppFolderPopup = class AppFolderPopup {
global.focus_manager.add_group(this.actor);
source.actor.connect('destroy', () => { this.actor.destroy(); });
source.actor.connect('destroy', () => this.actor.destroy());
this._grabHelper = new GrabHelper.GrabHelper(this.actor, {
actionMode: Shell.ActionMode.POPUP
});
@ -1346,22 +1331,22 @@ var AppFolderPopup = class AppFolderPopup {
let direction;
let isLtr = Clutter.get_default_text_direction() == Clutter.TextDirection.LTR;
switch (event.get_key_symbol()) {
case Clutter.Down:
direction = St.DirectionType.TAB_FORWARD;
break;
case Clutter.Right:
direction = isLtr ? St.DirectionType.TAB_FORWARD :
case Clutter.Down:
direction = St.DirectionType.TAB_FORWARD;
break;
case Clutter.Right:
direction = isLtr ? St.DirectionType.TAB_FORWARD :
St.DirectionType.TAB_BACKWARD;
break;
case Clutter.Up:
direction = St.DirectionType.TAB_BACKWARD;
break;
case Clutter.Left:
direction = isLtr ? St.DirectionType.TAB_BACKWARD :
break;
case Clutter.Up:
direction = St.DirectionType.TAB_BACKWARD;
break;
case Clutter.Left:
direction = isLtr ? St.DirectionType.TAB_BACKWARD :
St.DirectionType.TAB_FORWARD;
break;
default:
return Clutter.EVENT_PROPAGATE;
break;
default:
return Clutter.EVENT_PROPAGATE;
}
return actor.navigate_focus(null, direction, false);
}
@ -1393,9 +1378,9 @@ var AppFolderPopup = class AppFolderPopup {
this._boxPointer.open(BoxPointer.PopupAnimation.FADE |
BoxPointer.PopupAnimation.SLIDE,
() => {
this._view.actor.opacity = 255;
this._view.animate(IconGrid.AnimationDirection.IN);
});
this._view.actor.opacity = 255;
this._view.animate(IconGrid.AnimationDirection.IN);
});
this.emit('open-state-changed', true);
}
@ -1431,7 +1416,7 @@ var AppFolderPopup = class AppFolderPopup {
Signals.addSignalMethods(AppFolderPopup.prototype);
var AppIcon = class AppIcon {
constructor(app, iconParams) {
constructor(app, iconParams = {}) {
this.app = app;
this.id = app.get_id();
this.name = app.get_name();
@ -1457,9 +1442,6 @@ var AppIcon = class AppIcon {
this.actor._delegate = this;
if (!iconParams)
iconParams = {};
// Get the isDraggable property without passing it on to the BaseIcon:
let appIconParams = Params.parse(iconParams, { isDraggable: true }, true);
let isDraggable = appIconParams['isDraggable'];
@ -1491,7 +1473,7 @@ var AppIcon = class AppIcon {
Main.overview.cancelledItemDrag(this);
});
this._draggable.connect('drag-end', () => {
Main.overview.endItemDrag(this);
Main.overview.endItemDrag(this);
});
}
@ -1728,7 +1710,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
let appInfo = this._source.app.get_app_info();
let actions = appInfo.list_actions();
if (this._source.app.can_open_new_window() &&
actions.indexOf('new-window') == -1) {
!actions.includes('new-window')) {
this._newWindowMenuItem = this._appendMenuItem(_("New Window"));
this._newWindowMenuItem.connect('activate', () => {
if (this._source.app.state == Shell.AppState.STOPPED)
@ -1742,7 +1724,7 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
if (discreteGpuAvailable &&
this._source.app.state == Shell.AppState.STOPPED &&
actions.indexOf('activate-discrete-gpu') == -1) {
!actions.includes('activate-discrete-gpu')) {
this._onDiscreteGpuMenuItem = this._appendMenuItem(_("Launch using Dedicated Graphics Card"));
this._onDiscreteGpuMenuItem.connect('activate', () => {
if (this._source.app.state == Shell.AppState.STOPPED)

View File

@ -63,7 +63,7 @@ class AppFavorites {
constructor() {
this.FAVORITE_APPS_KEY = 'favorite-apps';
this._favorites = {};
global.settings.connect('changed::' + this.FAVORITE_APPS_KEY, this._onFavsChanged.bind(this));
global.settings.connect(`changed::${this.FAVORITE_APPS_KEY}`, this._onFavsChanged.bind(this));
this.reload();
}
@ -187,7 +187,7 @@ class AppFavorites {
}
});
}
};
}
Signals.addSignalMethods(AppFavorites.prototype);
var appFavoritesInstance = null;

View File

@ -1,4 +1,4 @@
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
@ -13,10 +13,11 @@ var AudioDevice = {
const AudioDeviceSelectionIface = loadInterfaceXML('org.gnome.Shell.AudioDeviceSelection');
var AudioDeviceSelectionDialog =
class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
constructor(devices) {
super({ styleClass: 'audio-device-selection-dialog' });
var AudioDeviceSelectionDialog = GObject.registerClass({
Signals: { 'device-selected': { param_types: [GObject.TYPE_UINT] } }
}, class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
_init(devices) {
super._init({ styleClass: 'audio-device-selection-dialog' });
this._deviceItems = {};
@ -33,10 +34,6 @@ class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
throw new Error('Too few devices for a selection');
}
destroy() {
super.destroy();
}
_buildLayout(devices) {
let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"),
@ -57,28 +54,28 @@ class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
}
_getDeviceLabel(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
case AudioDevice.HEADSET:
return _("Headset");
case AudioDevice.MICROPHONE:
return _("Microphone");
default:
return null;
switch (device) {
case AudioDevice.HEADPHONES:
return _("Headphones");
case AudioDevice.HEADSET:
return _("Headset");
case AudioDevice.MICROPHONE:
return _("Microphone");
default:
return null;
}
}
_getDeviceIcon(device) {
switch(device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
case AudioDevice.HEADSET:
return 'audio-headset-symbolic';
case AudioDevice.MICROPHONE:
return 'audio-input-microphone-symbolic';
default:
return null;
switch (device) {
case AudioDevice.HEADPHONES:
return 'audio-headphones-symbolic';
case AudioDevice.HEADSET:
return 'audio-headset-symbolic';
case AudioDevice.MICROPHONE:
return 'audio-input-microphone-symbolic';
default:
return null;
}
}
@ -113,11 +110,11 @@ class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
}
_openSettings() {
let desktopFile = 'gnome-sound-panel.desktop'
let desktopFile = 'gnome-sound-panel.desktop';
let app = Shell.AppSystem.get_default().lookup_app(desktopFile);
if (!app) {
log('Settings panel for desktop file ' + desktopFile + ' could not be loaded!');
log(`Settings panel for desktop file ${desktopFile} could not be loaded!`);
return;
}
@ -125,7 +122,7 @@ class AudioDeviceSelectionDialog extends ModalDialog.ModalDialog {
Main.overview.hide();
app.activate();
}
};
});
var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
constructor() {
@ -162,12 +159,12 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(n => { devices |= AudioDevice[n.toUpperCase()]; });
deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
let dialog;
try {
dialog = new AudioDeviceSelectionDialog(devices);
} catch(e) {
} catch (e) {
invocation.return_value(null);
return;
}

View File

@ -108,7 +108,6 @@ const PRIMARY_COLOR_KEY = 'primary-color';
const SECONDARY_COLOR_KEY = 'secondary-color';
const COLOR_SHADING_TYPE_KEY = 'color-shading-type';
const BACKGROUND_STYLE_KEY = 'picture-options';
const PICTURE_OPACITY_KEY = 'picture-opacity';
const PICTURE_URI_KEY = 'picture-uri';
var FADE_ANIMATION_TIME = 1.0;
@ -257,14 +256,15 @@ var Background = class Background {
this._refreshAnimation();
});
this._settingsChangedSignalId = this._settings.connect('changed', () => {
this.emit('changed');
});
this._settingsChangedSignalId =
this._settings.connect('changed', this._emitChangedSignal.bind(this));
this._load();
}
destroy() {
this.background = null;
this._cancellable.cancel();
this._removeAnimationTimeout();
@ -288,6 +288,22 @@ var Background = class Background {
if (this._settingsChangedSignalId != 0)
this._settings.disconnect(this._settingsChangedSignalId);
this._settingsChangedSignalId = 0;
if (this._changedIdleId) {
GLib.source_remove(this._changedIdleId);
this._changedIdleId = 0;
}
}
_emitChangedSignal() {
if (this._changedIdleId)
return;
this._changedIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._changedIdleId = 0;
this.emit('changed');
return GLib.SOURCE_REMOVE;
});
}
updateResolution() {
@ -343,7 +359,7 @@ var Background = class Background {
if (changedFile.equal(file)) {
let imageCache = Meta.BackgroundImageCache.get_default();
imageCache.purge(changedFile);
this.emit('changed');
this._emitChangedSignal();
}
});
this._fileWatches[key] = signalId;
@ -416,12 +432,12 @@ var Background = class Background {
return;
this._updateAnimationTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT,
interval,
() => {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
});
interval,
() => {
this._updateAnimationTimeoutId = 0;
this._updateAnimation();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._updateAnimationTimeoutId, '[gnome-shell] this._updateAnimation');
}
@ -448,9 +464,9 @@ var Background = class Background {
let cache = Meta.BackgroundImageCache.get_default();
let image = cache.load(file);
if (image.is_loaded())
if (image.is_loaded()) {
this._setLoaded();
else {
} else {
let id = image.connect('loaded', () => {
this._setLoaded();
image.disconnect(id);
@ -617,7 +633,7 @@ var Animation = class Animation {
}
load(callback) {
this._show = new GnomeDesktop.BGSlideShow({ filename: this.file.get_path() });
this._show = new GnomeDesktop.BGSlideShow({ file: this.file });
this._show.load_async(null, (object, result) => {
this.loaded = true;
@ -699,7 +715,6 @@ var BackgroundManager = class BackgroundManager {
time: FADE_ANIMATION_TIME,
transition: 'easeOutQuad',
onComplete() {
oldBackgroundActor.background.run_dispose();
oldBackgroundActor.destroy();
}
});

View File

@ -4,7 +4,7 @@ const { Atk, Clutter, St } = imports.gi;
const Signals = imports.signals;
var BarLevel = class {
constructor(value, params) {
constructor(value, params = {}) {
if (isNaN(value))
// Avoid spreading NaNs around
throw TypeError('The bar level value must be a number');
@ -13,9 +13,6 @@ var BarLevel = class {
this._overdriveStart = 1;
this._barLevelWidth = 0;
if (params == undefined)
params = {}
this.actor = new St.DrawingArea({ styleClass: params['styleClass'] || 'barlevel',
can_focus: params['canFocus'] || false,
reactive: params['reactive'] || false,
@ -105,7 +102,7 @@ var BarLevel = class {
overdriveSeparatorWidth = themeNode.get_length('-barlevel-overdrive-separator-width');
/* background bar */
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.arc(width - barLevelBorderRadius - barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
cr.lineTo(endX, (height + barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.lineTo(width - barLevelBorderRadius - barLevelBorderWidth, (height - barLevelHeight) / 2);
@ -117,12 +114,12 @@ var BarLevel = class {
/* normal progress bar */
let x = Math.min(endX, overdriveSeparatorX - overdriveSeparatorWidth / 2);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * 1 / 4, TAU * 3 / 4);
cr.arc(barLevelBorderRadius + barLevelBorderWidth, height / 2, barLevelBorderRadius, TAU * (1 / 4), TAU * (3 / 4));
cr.lineTo(x, (height - barLevelHeight) / 2);
cr.lineTo(x, (height + barLevelHeight) / 2);
cr.lineTo(barLevelBorderRadius + barLevelBorderWidth, (height + barLevelHeight) / 2);
if (this._value > 0)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
cr.fillPreserve();
Clutter.cairo_set_source_color(cr, barLevelActiveBorderColor);
cr.setLineWidth(barLevelBorderWidth);
@ -145,17 +142,17 @@ var BarLevel = class {
/* end progress bar arc */
if (this._value > 0) {
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * 3 / 4, TAU * 1 / 4);
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
if (this._value <= this._overdriveStart)
Clutter.cairo_set_source_color(cr, barLevelActiveColor);
else
Clutter.cairo_set_source_color(cr, barLevelOverdriveColor);
cr.arc(endX, height / 2, barLevelBorderRadius, TAU * (3 / 4), TAU * (1 / 4));
cr.lineTo(Math.floor(endX), (height + barLevelHeight) / 2);
cr.lineTo(Math.floor(endX), (height - barLevelHeight) / 2);
cr.lineTo(endX, (height - barLevelHeight) / 2);
cr.fillPreserve();
cr.setLineWidth(barLevelBorderWidth);
cr.stroke();
}
/* draw overdrive separator */

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, GObject, Shell, St } = imports.gi;
const Main = imports.ui.main;
const Tweener = imports.ui.tweener;
@ -48,6 +48,15 @@ var BoxPointer = GObject.registerClass({
this._sourceAlignment = 0.5;
this._capturedEventId = 0;
this._muteInput();
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
delete this._sourceActorDestroyId;
}
}
get arrowSide() {
@ -67,36 +76,6 @@ var BoxPointer = GObject.registerClass({
}
}
// BoxPointer.show() and BoxPointer.hide() are here for only compatibility
// purposes, and will be removed in 3.32.
show(animate, onComplete) {
if (animate !== undefined) {
try {
throw new Error('BoxPointer.show() has been moved to BoxPointer.open(), this code will break in the future.');
} catch(e) {
logError(e);
this.open(animate, onComplete);
return;
}
}
this.visible = true;
}
hide(animate, onComplete) {
if (animate !== undefined) {
try {
throw new Error('BoxPointer.hide() has been moved to BoxPointer.close(), this code will break in the future.');
} catch(e) {
logError(e);
this.close(animate, onComplete);
return;
}
}
this.visible = false;
}
open(animate, onComplete) {
let themeNode = this.get_theme_node();
let rise = themeNode.get_length('-arrow-rise');
@ -111,18 +90,18 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
this.translation_y = -rise;
break;
case St.Side.BOTTOM:
this.translation_y = rise;
break;
case St.Side.LEFT:
this.translation_x = -rise;
break;
case St.Side.RIGHT:
this.translation_x = rise;
break;
case St.Side.TOP:
this.translation_y = -rise;
break;
case St.Side.BOTTOM:
this.translation_y = rise;
break;
case St.Side.LEFT:
this.translation_x = -rise;
break;
case St.Side.RIGHT:
this.translation_x = rise;
break;
}
}
@ -151,18 +130,18 @@ var BoxPointer = GObject.registerClass({
if (animate & PopupAnimation.SLIDE) {
switch (this._arrowSide) {
case St.Side.TOP:
translationY = rise;
break;
case St.Side.BOTTOM:
translationY = -rise;
break;
case St.Side.LEFT:
translationX = rise;
break;
case St.Side.RIGHT:
translationX = -rise;
break;
case St.Side.TOP:
translationY = rise;
break;
case St.Side.BOTTOM:
translationY = -rise;
break;
case St.Side.LEFT:
translationX = rise;
break;
case St.Side.RIGHT:
translationX = -rise;
break;
}
}
@ -225,13 +204,10 @@ var BoxPointer = GObject.registerClass({
this.set_allocation(box, flags);
let themeNode = this.get_theme_node();
box = themeNode.get_content_box(box);
let borderWidth = themeNode.get_length('-arrow-border-width');
let rise = themeNode.get_length('-arrow-rise');
let childBox = new Clutter.ActorBox();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let [availWidth, availHeight] = themeNode.get_content_box(box).get_size();
childBox.x1 = 0;
childBox.y1 = 0;
@ -244,24 +220,25 @@ var BoxPointer = GObject.registerClass({
childBox.x2 = availWidth - borderWidth;
childBox.y2 = availHeight - borderWidth;
switch (this._arrowSide) {
case St.Side.TOP:
childBox.y1 += rise;
break;
case St.Side.BOTTOM:
childBox.y2 -= rise;
break;
case St.Side.LEFT:
childBox.x1 += rise;
break;
case St.Side.RIGHT:
childBox.x2 -= rise;
break;
case St.Side.TOP:
childBox.y1 += rise;
break;
case St.Side.BOTTOM:
childBox.y2 -= rise;
break;
case St.Side.LEFT:
childBox.x1 += rise;
break;
case St.Side.RIGHT:
childBox.x2 -= rise;
break;
}
this.bin.allocate(childBox, flags);
if (this._sourceActor && this._sourceActor.mapped) {
this._reposition();
this._updateFlip();
this._reposition(box);
this._updateFlip(box);
this.set_allocation(box, flags);
}
}
@ -287,7 +264,7 @@ var BoxPointer = GObject.registerClass({
let borderRadius = themeNode.get_length('-arrow-border-radius');
let halfBorder = borderWidth / 2;
let halfBase = Math.floor(base/2);
let halfBase = Math.floor(base / 2);
let backgroundColor = themeNode.get_color('-arrow-background-color');
@ -368,7 +345,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopRight) {
cr.lineTo(x2 - borderRadius, y1);
cr.arc(x2 - borderRadius, y1 + borderRadius, borderRadius,
3*Math.PI/2, Math.PI*2);
3 * Math.PI / 2, Math.PI * 2);
}
if (this._arrowSide == St.Side.RIGHT && rise) {
@ -389,7 +366,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomRight) {
cr.lineTo(x2, y2 - borderRadius);
cr.arc(x2 - borderRadius, y2 - borderRadius, borderRadius,
0, Math.PI/2);
0, Math.PI / 2);
}
if (this._arrowSide == St.Side.BOTTOM && rise) {
@ -410,7 +387,7 @@ var BoxPointer = GObject.registerClass({
if (!skipBottomLeft) {
cr.lineTo(x1 + borderRadius, y2);
cr.arc(x1 + borderRadius, y2 - borderRadius, borderRadius,
Math.PI/2, Math.PI);
Math.PI / 2, Math.PI);
}
if (this._arrowSide == St.Side.LEFT && rise) {
@ -419,7 +396,7 @@ var BoxPointer = GObject.registerClass({
cr.lineTo(x1 - rise, y1);
cr.lineTo(x1 + borderRadius, y1);
} else if (skipBottomLeft) {
cr.lineTo(x1 - rise, y2)
cr.lineTo(x1 - rise, y2);
cr.lineTo(x1 - rise, y2 - halfBase);
} else {
cr.lineTo(x1, this._arrowOrigin + halfBase);
@ -431,7 +408,7 @@ var BoxPointer = GObject.registerClass({
if (!skipTopLeft) {
cr.lineTo(x1, y1 + borderRadius);
cr.arc(x1 + borderRadius, y1 + borderRadius, borderRadius,
Math.PI, 3*Math.PI/2);
Math.PI, 3 * Math.PI / 2);
}
Clutter.cairo_set_source_color(cr, backgroundColor);
@ -448,15 +425,25 @@ var BoxPointer = GObject.registerClass({
}
setPosition(sourceActor, alignment) {
// We need to show it now to force an allocation,
// so that we can query the correct size.
this.show();
if (!this._sourceActor || sourceActor != this._sourceActor) {
if (this._sourceActorDestroyId) {
this._sourceActor.disconnect(this._sourceActorDestroyId);
delete this._sourceActorDestroyId;
}
this._sourceActor = sourceActor;
if (this._sourceActor) {
this._sourceActorDestroyId = this._sourceActor.connect('destroy', () => {
this._sourceActor = null;
delete this._sourceActorDestroyId;
});
}
}
this._sourceActor = sourceActor;
this._arrowAlignment = alignment;
this._reposition();
this._updateFlip();
this.queue_relayout();
}
setSourceAlignment(alignment) {
@ -468,7 +455,7 @@ var BoxPointer = GObject.registerClass({
this.setPosition(this._sourceActor, this._arrowAlignment);
}
_reposition() {
_reposition(allocationBox) {
let sourceActor = this._sourceActor;
let alignment = this._arrowAlignment;
let monitorIndex = Main.layoutManager.findIndexForActor(sourceActor);
@ -526,7 +513,7 @@ var BoxPointer = GObject.registerClass({
// of the box to maintain the arrow's accuracy.
let arrowOrigin;
let halfBase = Math.floor(arrowBase/2);
let halfBase = Math.floor(arrowBase / 2);
let halfBorder = borderWidth / 2;
let halfMargin = margin / 2;
let [x1, y1] = [halfBorder, halfBorder];
@ -582,8 +569,7 @@ var BoxPointer = GObject.registerClass({
}
// Actually set the position
this.x = Math.floor(x);
this.y = Math.floor(y);
allocationBox.set_origin(Math.floor(x), Math.floor(y));
}
// @origin: Coordinate specifying middle of the arrow, along
@ -637,15 +623,11 @@ var BoxPointer = GObject.registerClass({
return arrowSide;
}
_updateFlip() {
_updateFlip(allocationBox) {
let arrowSide = this._calculateArrowSide(this._userArrowSide);
if (this._arrowSide != arrowSide) {
this._arrowSide = arrowSide;
this._reposition();
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this.queue_relayout();
return false;
});
this._reposition(allocationBox);
this.emit('arrow-side-changed');
}

View File

@ -17,7 +17,7 @@ var ELLIPSIS_CHAR = '\u2026';
var MESSAGE_ICON_SIZE = -1; // pick up from CSS
var NC_ = (context, str) => context + '\u0004' + str;
var NC_ = (context, str) => `${context}\u0004${str}`;
function sameYear(dateA, dateB) {
return (dateA.getYear() == dateB.getYear());
@ -38,7 +38,7 @@ function isToday(date) {
function _isWorkDay(date) {
/* Translators: Enter 0-6 (Sunday-Saturday) for non-work days. Examples: "0" (Sunday) "6" (Saturday) "06" (Sunday and Saturday). */
let days = C_('calendar-no-work', "06");
return days.indexOf(date.getDay().toString()) == -1;
return !days.includes(date.getDay().toString());
}
function _getBeginningOfDay(date) {
@ -143,8 +143,7 @@ function _datesEqual(a, b) {
return true;
}
function _dateIntervalsOverlap(a0, a1, b0, b1)
{
function _dateIntervalsOverlap(a0, a1, b0, b1) {
if (a1 <= b0)
return false;
else if (b1 <= a0)
@ -168,7 +167,7 @@ var DBusEventSource = class DBusEventSource {
try {
this._dbusProxy.init_finish(result);
loaded = true;
} catch(e) {
} catch (e) {
if (e.matches(Gio.DBusError, Gio.DBusError.TIMED_OUT)) {
// Ignore timeouts and install signals as normal, because with high
// probability the service will appear later on, and we will get a
@ -178,7 +177,7 @@ var DBusEventSource = class DBusEventSource {
// about the HasCalendars property and would cause an exception trying
// to read it)
} else {
log('Error loading calendars: ' + e.message);
log(`Error loading calendars: ${e.message}`);
return;
}
}
@ -238,20 +237,18 @@ var DBusEventSource = class DBusEventSource {
_onEventsReceived(results, error) {
let newEvents = [];
let appointments = results ? results[0] : null;
if (appointments != null) {
for (let n = 0; n < appointments.length; n++) {
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
let appointments = results[0] || [];
for (let n = 0; n < appointments.length; n++) {
let a = appointments[n];
let date = new Date(a[4] * 1000);
let end = new Date(a[5] * 1000);
let id = a[0];
let summary = a[1];
let allDay = a[3];
let event = new CalendarEvent(id, date, end, summary, allDay);
newEvents.push(event);
}
newEvents.sort((ev1, ev2) => ev1.date.getTime() - ev2.date.getTime());
this._events = newEvents;
this.isLoading = false;
@ -263,7 +260,7 @@ var DBusEventSource = class DBusEventSource {
if (!this._initialized)
return;
if (this._curRequestBegin && this._curRequestEnd){
if (this._curRequestBegin && this._curRequestEnd) {
this._dbusProxy.GetEventsRemote(this._curRequestBegin.getTime() / 1000,
this._curRequestEnd.getTime() / 1000,
forceReload,
@ -285,7 +282,7 @@ var DBusEventSource = class DBusEventSource {
getEvents(begin, end) {
let result = [];
for(let n = 0; n < this._events.length; n++) {
for (let n = 0; n < this._events.length; n++) {
let event = this._events[n];
if (_dateIntervalsOverlap (event.date, event.end, begin, end)) {
@ -320,7 +317,7 @@ var Calendar = class Calendar {
this._weekStart = Shell.util_get_week_start();
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.calendar' });
this._settings.connect('changed::' + SHOW_WEEKDATE_KEY, this._onSettingsChange.bind(this));
this._settings.connect(`changed::${SHOW_WEEKDATE_KEY}`, this._onSettingsChange.bind(this));
this._useWeekdate = this._settings.get_boolean(SHOW_WEEKDATE_KEY);
/**
@ -402,8 +399,8 @@ var Calendar = class Calendar {
this._topBox.add(this._backButton);
this._backButton.connect('clicked', this._onPrevMonthButtonClicked.bind(this));
this._monthLabel = new St.Label({style_class: 'calendar-month-label',
can_focus: true });
this._monthLabel = new St.Label({ style_class: 'calendar-month-label',
can_focus: true });
this._topBox.add(this._monthLabel, { expand: true, x_fill: false, x_align: St.Align.MIDDLE });
this._forwardButton = new St.Button({ style_class: 'calendar-change-month-forward pager-button',
@ -466,8 +463,7 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() - 1, 11, 32).getDate();
newDate = new Date(newDate.getFullYear() - 1, 11, day);
}
}
else {
} else {
newDate.setMonth(oldMonth - 1);
if (newDate.getMonth() != oldMonth - 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth - 1, 32).getDate();
@ -490,8 +486,7 @@ var Calendar = class Calendar {
let day = 32 - new Date(newDate.getFullYear() + 1, 0, 32).getDate();
newDate = new Date(newDate.getFullYear() + 1, 0, day);
}
}
else {
} else {
newDate.setMonth(oldMonth + 1);
if (newDate.getMonth() != oldMonth + 1) {
let day = 32 - new Date(newDate.getFullYear(), oldMonth + 1, 32).getDate();
@ -546,8 +541,6 @@ var Calendar = class Calendar {
this._calendarBegin = new Date(beginDate);
this._markedAsToday = now;
let year = beginDate.getYear();
let daysToWeekStart = (7 + beginDate.getDay() - this._weekStart) % 7;
let startsOnWeekStart = daysToWeekStart == 0;
let weekPadding = startsOnWeekStart ? 7 : 0;
@ -559,7 +552,7 @@ var Calendar = class Calendar {
let row = 2;
// nRows here means 6 weeks + one header + one navbar
let nRows = 8;
while (row < 8) {
while (row < nRows) {
// xgettext:no-javascript-format
let button = new St.Button({ label: iter.toLocaleFormat(C_("date day number format", "%d")),
can_focus: true });
@ -585,12 +578,12 @@ var Calendar = class Calendar {
// Hack used in lieu of border-collapse - see gnome-shell.css
if (row == 2)
styleClass = 'calendar-day-top ' + styleClass;
styleClass = `calendar-day-top ${styleClass}`;
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
if (leftMost)
styleClass = 'calendar-day-left ' + styleClass;
styleClass = `calendar-day-left ${styleClass}`;
if (sameDay(now, iter))
styleClass += ' calendar-today';
@ -648,9 +641,9 @@ var Calendar = class Calendar {
button.add_style_pseudo_class('selected');
if (this._shouldDateGrabFocus)
button.grab_key_focus();
}
else
} else {
button.remove_style_pseudo_class('selected');
}
});
}
};
@ -1077,7 +1070,7 @@ var CalendarMessageList = class CalendarMessageList {
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()];
sections.forEach((s) => { s.clear(); });
sections.forEach((s) => s.clear());
});
box.add_actor(this._clearButton);
@ -1103,7 +1096,7 @@ var CalendarMessageList = class CalendarMessageList {
_addSection(section) {
let obj = {
destroyId: 0,
visibleId: 0,
visibleId: 0,
emptyChangedId: 0,
canClearChangedId: 0,
keyFocusId: 0

View File

@ -6,12 +6,12 @@ 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 FROZEN_WINDOW_BRIGHTNESS = -0.3;
var DIALOG_TRANSITION_TIME = 0.15;
var ALIVE_TIMEOUT = 5000;
var CloseDialog = GObject.registerClass({
Implements: [ Meta.CloseDialog ],
Implements: [Meta.CloseDialog],
Properties: {
'window': GObject.ParamSpec.override('window', Meta.CloseDialog)
},
@ -56,12 +56,12 @@ var CloseDialog = GObject.registerClass({
this._dialog.height = windowActor.height;
this._dialog.addContent(this._createDialogContent());
this._dialog.addButton({ label: _('Force Quit'),
action: this._onClose.bind(this),
this._dialog.addButton({ label: _('Force Quit'),
action: this._onClose.bind(this),
default: true });
this._dialog.addButton({ label: _('Wait'),
this._dialog.addButton({ label: _('Wait'),
action: this._onWait.bind(this),
key: Clutter.Escape });
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
}
@ -165,7 +165,7 @@ var CloseDialog = GObject.registerClass({
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
global.display.disconnect(this._windowFocusChangedId)
global.display.disconnect(this._windowFocusChangedId);
this._windowFocusChangedId = 0;
global.stage.disconnect(this._keyFocusChangedId);

View File

@ -13,13 +13,13 @@ var ComponentManager = class {
let newEnabledComponents = Main.sessionMode.components;
newEnabledComponents.filter(
name => this._enabledComponents.indexOf(name) == -1
name => !this._enabledComponents.includes(name)
).forEach(name => {
this._enableComponent(name);
});
this._enabledComponents.filter(
name => newEnabledComponents.indexOf(name) == -1
name => !newEnabledComponents.includes(name)
).forEach(name => {
this._disableComponent(name);
});
@ -37,8 +37,8 @@ var ComponentManager = class {
if (component)
return component;
if (Main.sessionMode.isLocked)
return null;
if (Main.sessionMode.isLocked)
return null;
let constructor = this._importComponent(name);
component = new constructor();
@ -48,7 +48,7 @@ var ComponentManager = class {
_enableComponent(name) {
let component = this._ensureComponent(name);
if (component)
if (component)
component.enable();
}

View File

@ -109,25 +109,23 @@ var AutomountManager = class {
// we force stop/eject in this case, so we don't have to pass a
// mount operation object
if (drive.can_stop()) {
drive.stop
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
log("Unable to stop the drive after drive-eject-button " + e.toString());
}
});
drive.stop(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.stop_finish(res);
} catch (e) {
log(`Unable to stop the drive after drive-eject-button ${e.toString()}`);
}
});
} else if (drive.can_eject()) {
drive.eject_with_operation
(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
log("Unable to eject the drive after drive-eject-button " + e.toString());
}
});
drive.eject_with_operation(Gio.MountUnmountFlags.FORCE, null, null,
(drive, res) => {
try {
drive.eject_with_operation_finish(res);
} catch (e) {
log(`Unable to eject the drive after drive-eject-button ${e.toString()}`);
}
});
}
}
@ -213,7 +211,7 @@ var AutomountManager = class {
}
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED_HANDLED))
log('Unable to mount volume ' + volume.get_name() + ': ' + e.toString());
log(`Unable to mount volume ${volume.get_name()}: ${e.toString()}`);
this._closeOperation(volume);
}
}

View File

@ -40,7 +40,7 @@ function isMountRootHidden(root) {
let path = root.get_path();
// skip any mounts in hidden directory hierarchies
return (path.indexOf('/.') != -1);
return (path.includes('/.'));
}
function isMountNonLocal(mount) {
@ -65,8 +65,7 @@ function startAppForMount(app, mount) {
retval = app.launch(files,
global.create_app_launch_context(0, -1));
} catch (e) {
log('Unable to launch the application ' + app.get_name()
+ ': ' + e.toString());
log(`Unable to launch the application ${app.get_name()}: ${e}`);
}
return retval;
@ -107,8 +106,7 @@ var ContentTypeDiscoverer = class {
try {
contentTypes = mount.guess_content_type_finish(res);
} catch (e) {
log('Unable to guess content types on added mount ' + mount.get_name()
+ ': ' + e.toString());
log(`Unable to guess content types on added mount ${mount.get_name()}: ${e}`);
}
if (contentTypes.length) {
@ -124,10 +122,7 @@ var ContentTypeDiscoverer = class {
}
}
_emitCallback(mount, contentTypes) {
if (!contentTypes)
contentTypes = [];
_emitCallback(mount, contentTypes = []) {
// we're not interested in win32 software content types here
contentTypes = contentTypes.filter(
type => (type != 'x-content/win32-software')
@ -192,15 +187,15 @@ var AutorunDispatcher = class {
_getAutorunSettingForType(contentType) {
let runApp = this._settings.get_strv(SETTING_START_APP);
if (runApp.indexOf(contentType) != -1)
if (runApp.includes(contentType))
return AutorunSetting.RUN;
let ignore = this._settings.get_strv(SETTING_IGNORE);
if (ignore.indexOf(contentType) != -1)
if (ignore.includes(contentType))
return AutorunSetting.IGNORE;
let openFiles = this._settings.get_strv(SETTING_OPEN_FOLDER);
if (openFiles.indexOf(contentType) != -1)
if (openFiles.includes(contentType))
return AutorunSetting.FILES;
return AutorunSetting.ASK;

View File

@ -10,9 +10,10 @@ const CheckBox = imports.ui.checkBox;
var WORK_SPINNER_ICON_SIZE = 16;
var KeyringDialog = class extends ModalDialog.ModalDialog {
constructor() {
super({ styleClass: 'prompt-dialog' });
var KeyringDialog = GObject.registerClass(
class KeyringDialog extends ModalDialog.ModalDialog {
_init() {
super._init({ styleClass: 'prompt-dialog' });
this.prompt = new Shell.KeyringPrompt();
this.prompt.connect('show-password', this._onShowPassword.bind(this));
@ -161,7 +162,7 @@ var KeyringDialog = class extends ModalDialog.ModalDialog {
// NOTE: ModalDialog.open() is safe to call if the dialog is
// already open - it just returns true without side-effects
if (this.open())
return true;
return true;
// The above fail if e.g. unable to get input grab
//
@ -171,7 +172,7 @@ var KeyringDialog = class extends ModalDialog.ModalDialog {
log('keyringPrompt: Failed to show modal dialog.' +
' Dismissing prompt request');
this.prompt.cancel()
this.prompt.cancel();
return false;
}
@ -212,7 +213,7 @@ var KeyringDialog = class extends ModalDialog.ModalDialog {
_onCancelButton() {
this.prompt.cancel();
}
};
});
var KeyringDummyDialog = class {
constructor() {

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, NM, Pango, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Config = imports.misc.config;
@ -12,9 +12,10 @@ const ShellEntry = imports.ui.shellEntry;
const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
constructor(agent, requestId, connection, settingName, hints, flags, contentOverride) {
super({ styleClass: 'prompt-dialog' });
var NetworkSecretDialog = GObject.registerClass(
class NetworkSecretDialog extends ModalDialog.ModalDialog {
_init(agent, requestId, connection, settingName, hints, flags, contentOverride) {
super._init({ styleClass: 'prompt-dialog' });
this._agent = agent;
this._requestId = requestId;
@ -79,8 +80,9 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
secret.valid = secret.value.length > 0;
this._updateOkButton();
});
} else
} else {
secret.valid = true;
}
if (rtl) {
layout.attach(secret.entry, 0, pos, 1, 1);
@ -104,19 +106,19 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
descriptionLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
contentBox.messageBox.add(descriptionLabel,
{ y_fill: true,
{ y_fill: true,
y_align: St.Align.START,
expand: true });
}
this._okButton = { label: _("Connect"),
this._okButton = { label: _("Connect"),
action: this._onOk.bind(this),
default: true
};
this.setButtons([{ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
key: Clutter.KEY_Escape,
},
this._okButton]);
@ -175,24 +177,25 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
let value = secret.value;
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
return false;
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'z')
|| (value[i] >= 'A' && value[i] <= 'Z')))
return false;
}
} else
} else {
return false;
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64)
return false;
}
}
} else if (secret.wep_key_type == NM.WepKeyType.PASSPHRASE) {
if (value.length < 0 || value.length > 64)
return false;
}
return true;
}
@ -213,7 +216,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
validate: this._validateWpaPsk, password: true });
break;
case 'none': // static WEP
secrets.push({ label: _("Key: "), key: 'wep-key' + wirelessSecuritySetting.wep_tx_keyidx,
secrets.push({ label: _("Key: "), key: `wep-key${wirelessSecuritySetting.wep_tx_keyidx}`,
value: wirelessSecuritySetting.get_wep_key(wirelessSecuritySetting.wep_tx_keyidx) || '',
wep_key_type: wirelessSecuritySetting.wep_key_type,
validate: this._validateStaticWep, password: true });
@ -229,13 +232,12 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
this._get8021xSecrets(secrets);
break;
default:
log('Invalid wireless key management: ' + wirelessSecuritySetting.key_mgmt);
log(`Invalid wireless key management: ${wirelessSecuritySetting.key_mgmt}`);
}
}
_get8021xSecrets(secrets) {
let ieee8021xSetting = this._connection.get_setting_802_1x();
let phase2method;
/* If hints were given we know exactly what we need to ask */
if (this._settingName == "802-1x" && this._hints.length) {
@ -272,7 +274,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
value: ieee8021xSetting.private_key_password || '', password: true });
break;
default:
log('Invalid EAP/IEEE802.1x method: ' + ieee8021xSetting.get_eap_method(0));
log(`Invalid EAP/IEEE802.1x method: ${ieee8021xSetting.get_eap_method(0)}`);
}
}
@ -303,7 +305,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
let ssid;
let content = { };
content.secrets = [ ];
content.secrets = [];
switch (connectionType) {
case '802-11-wireless':
@ -326,7 +328,7 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
this._getPPPoESecrets(content.secrets);
break;
case 'gsm':
if (this._hints.indexOf('pin') != -1) {
if (this._hints.includes('pin')) {
let gsmSetting = this._connection.get_setting_gsm();
content.title = _("PIN code required");
content.message = _("PIN code is needed for the mobile broadband device");
@ -342,12 +344,12 @@ var NetworkSecretDialog = class extends ModalDialog.ModalDialog {
this._getMobileSecrets(content.secrets, connectionType);
break;
default:
log('Invalid connection type: ' + connectionType);
};
log(`Invalid connection type: ${connectionType}`);
}
return content;
}
};
});
var VPNRequestHandler = class {
constructor(agent, requestId, authHelper, serviceType, connection, hints, flags) {
@ -358,16 +360,15 @@ var VPNRequestHandler = class {
this._pluginOutBuffer = [];
this._title = null;
this._description = null;
this._content = [ ];
this._content = [];
this._shellDialog = null;
let connectionSetting = connection.get_setting_connection();
let argv = [ authHelper.fileName,
'-u', connectionSetting.uuid,
'-n', connectionSetting.id,
'-s', serviceType
];
let argv = [authHelper.fileName,
'-u', connectionSetting.uuid,
'-n', connectionSetting.id,
'-s', serviceType];
if (authHelper.externalUIMode)
argv.push('--external-ui-mode');
if (flags & NM.SecretAgentGetSecretsFlags.ALLOW_INTERACTION)
@ -406,7 +407,7 @@ var VPNRequestHandler = class {
this._vpnChildFinished.bind(this));
this._writeConnection();
} catch(e) {
} catch (e) {
logError(e, 'error while spawning VPN auth helper');
this._agent.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
@ -423,7 +424,7 @@ var VPNRequestHandler = class {
} else {
try {
this._stdin.write('QUIT\n\n', null);
} catch(e) { /* ignore broken pipe errors */ }
} catch (e) { /* ignore broken pipe errors */ }
}
this.destroy();
@ -458,8 +459,9 @@ var VPNRequestHandler = class {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.USER_CANCELED);
else
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.CONFIRMED);
} else
} else {
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
}
this.destroy();
}
@ -472,7 +474,7 @@ var VPNRequestHandler = class {
if (line == '' && this._previousLine == '') {
try {
this._stdin.write('QUIT\n\n', null);
} catch(e) { /* ignore broken pipe errors */ }
} catch (e) { /* ignore broken pipe errors */ }
} else {
this._agent.set_password(this._requestId, this._previousLine, line);
this._previousLine = undefined;
@ -560,7 +562,7 @@ var VPNRequestHandler = class {
this._agent.set_password(this._requestId, groups[i], value);
}
}
} catch(e) {
} catch (e) {
// No output is a valid case it means "both secrets are stored"
if (data.length > 0) {
logError(e, 'error while reading VPN plugin output keyfile');
@ -586,15 +588,15 @@ var VPNRequestHandler = class {
try {
vpnSetting.foreach_data_item((key, value) => {
this._stdin.write('DATA_KEY=' + key + '\n', null);
this._stdin.write('DATA_VAL=' + (value || '') + '\n\n', null);
this._stdin.write(`DATA_KEY=${key}\n`, null);
this._stdin.write(`DATA_VAL=${value || ''}\n\n`, null);
});
vpnSetting.foreach_secret((key, value) => {
this._stdin.write('SECRET_KEY=' + key + '\n', null);
this._stdin.write('SECRET_VAL=' + (value || '') + '\n\n', null);
this._stdin.write(`SECRET_KEY=${key}\n`, null);
this._stdin.write(`SECRET_VAL=${value || ''}\n\n`, null);
});
this._stdin.write('DONE\n\n', null);
} catch(e) {
} catch (e) {
logError(e, 'internal error while writing connection to helper');
this._agent.respond(this._requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
@ -618,9 +620,9 @@ var NetworkAgent = class {
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => { this._vpnCacheBuilt = false; });
} catch(e) {
log('Failed to create monitor for VPN plugin dir: ' + e.message);
monitor.connect('changed', () => this._vpnCacheBuilt = false);
} catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
}
this._native.connect('new-request', this._newRequest.bind(this));
@ -631,7 +633,7 @@ var NetworkAgent = class {
try {
this._native.init_finish(res);
this._initialized = true;
} catch(e) {
} catch (e) {
this._native = null;
logError(e, 'error initializing the NetworkManager Agent');
}
@ -679,12 +681,13 @@ var NetworkAgent = class {
let connectionSetting = connection.get_setting_connection();
let connectionType = connectionSetting.get_connection_type();
switch (connectionType) {
case '802-11-wireless':
case '802-11-wireless': {
let wirelessSetting = connection.get_setting_wireless();
let ssid = NM.utils_ssid_to_utf8(wirelessSetting.get_ssid().get_data());
title = _("Authentication required by wireless network");
body = _("Passwords or encryption keys are required to access the wireless network “%s”.").format(ssid);
break;
}
case '802-3-ethernet':
title = _("Wired 802.1X authentication");
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
@ -694,8 +697,7 @@ var NetworkAgent = class {
body = _("A password is required to connect to “%s”.".format(connection.get_id()));
break;
case 'gsm':
if (hints.indexOf('pin') != -1) {
let gsmSetting = connection.get_setting_gsm();
if (hints.includes('pin')) {
title = _("PIN code required");
body = _("PIN code is needed for the mobile broadband device");
break;
@ -707,7 +709,7 @@ var NetworkAgent = class {
body = _("A password is required to connect to “%s”.").format(connectionSetting.get_id());
break;
default:
log('Invalid connection type: ' + connectionType);
log(`Invalid connection type: ${connectionType}`);
this._native.respond(requestId, Shell.NetworkAgentResponse.INTERNAL_ERROR);
return;
}

View File

@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { AccountsService, Clutter, Gio, GLib,
Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
const Signals = imports.signals;
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
const Animation = imports.ui.animation;
const Dialog = imports.ui.dialog;
@ -15,9 +14,11 @@ var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16;
var AuthenticationDialog = class extends ModalDialog.ModalDialog {
constructor(actionId, body, cookie, userNames) {
super({ styleClass: 'prompt-dialog' });
var AuthenticationDialog = GObject.registerClass({
Signals: { 'done': { param_types: [GObject.TYPE_BOOLEAN] } }
}, class AuthenticationDialog extends ModalDialog.ModalDialog {
_init(actionId, body, cookie, userNames) {
super._init({ styleClass: 'prompt-dialog' });
this.actionId = actionId;
this.message = body;
@ -25,7 +26,7 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
this._wasDismissed = false;
this._sessionUpdatedId = Main.sessionMode.connect('updated', () => {
this._group.visible = !Main.sessionMode.isLocked;
this.visible = !Main.sessionMode.isLocked;
});
this.connect('closed', this._onDialogClosed.bind(this));
@ -37,19 +38,19 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
this.contentLayout.add_actor(content);
if (userNames.length > 1) {
log('polkitAuthenticationAgent: Received ' + userNames.length +
' identities that can be used for authentication. Only ' +
log(`polkitAuthenticationAgent: Received ${userNames.length} ` +
'identities that can be used for authentication. Only ' +
'considering one.');
}
let userName = GLib.get_user_name();
if (userNames.indexOf(userName) < 0)
if (!userNames.includes(userName))
userName = 'root';
if (userNames.indexOf(userName) < 0)
if (!userNames.includes(userName))
userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name()
let userRealName = this._user.get_real_name();
this._userLoadedId = this._user.connect('notify::is_loaded',
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
@ -76,15 +77,15 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
text: userRealName }));
userBox.add(userLabel,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
}
@ -97,7 +98,7 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
this._passwordBox.add(this._passwordLabel, { y_fill: false, y_align: St.Align.MIDDLE });
this._passwordEntry = new St.Entry({ style_class: 'prompt-dialog-password-entry',
text: "",
can_focus: true});
can_focus: true });
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onEntryActivate.bind(this));
this._passwordBox.add(this._passwordEntry,
@ -126,7 +127,7 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
* gnome-shell.css sets the color to be transparent
*/
this._nullMessageLabel = new St.Label({ style_class: 'prompt-dialog-null-label',
text: 'abc'});
text: 'abc' });
this._nullMessageLabel.add_style_class_name('hidden');
this._nullMessageLabel.clutter_text.ellipsize = Pango.EllipsizeMode.NONE;
this._nullMessageLabel.clutter_text.line_wrap = true;
@ -136,7 +137,7 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
this._cancelButton = this.addButton({ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.Escape });
this._okButton = this.addButton({ label: _("Authenticate"),
this._okButton = this.addButton({ label: _("Authenticate"),
action: this._onAuthenticateButtonPressed.bind(this),
default: true });
@ -179,9 +180,9 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
//
// We could add retrying if this turns out to be a problem
log('polkitAuthenticationAgent: Failed to show modal dialog.' +
' Dismissing authentication request for action-id ' + this.actionId +
' cookie ' + this._cookie);
log('polkitAuthenticationAgent: Failed to show modal dialog. ' +
`Dismissing authentication request for action-id ${this.actionId} ` +
`cookie ${this._cookie}`);
this._emitDone(true);
}
}
@ -249,14 +250,14 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
}
}
_onSessionRequest(session, request, echo_on) {
_onSessionRequest(session, request, echoOn) {
// Cheap localization trick
if (request == 'Password:' || request == 'Password: ')
this._passwordLabel.set_text(_("Password:"));
else
this._passwordLabel.set_text(request);
if (echo_on)
if (echoOn)
this._passwordEntry.clutter_text.set_password_char('');
else
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
@ -326,8 +327,7 @@ var AuthenticationDialog = class extends ModalDialog.ModalDialog {
this._destroySession();
}
};
Signals.addSignalMethods(AuthenticationDialog.prototype);
});
var AuthenticationAgent = class {
constructor() {
@ -342,7 +342,7 @@ var AuthenticationAgent = class {
enable() {
try {
this._native.register();
} catch(e) {
} catch (e) {
log('Failed to register AuthenticationAgent');
}
}
@ -350,7 +350,7 @@ var AuthenticationAgent = class {
disable() {
try {
this._native.unregister();
} catch(e) {
} catch (e) {
log('Failed to unregister AuthenticationAgent');
}
}

View File

@ -8,7 +8,7 @@ var Tpl = null;
var Tp = null;
try {
({ TelepathyGLib: Tp, TelepathyLogger: Tpl } = imports.gi);
} catch(e) {
} catch (e) {
log('Telepathy is not available, chat integration will be disabled.');
}
@ -40,8 +40,6 @@ var NotificationDirection = {
RECEIVED: 'chat-received'
};
var N_ = s => s;
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text();
@ -89,7 +87,7 @@ var TelepathyComponent = class {
try {
this._client.register();
} catch (e) {
throw new Error('Couldn\'t register Telepathy client. Error: \n' + e);
throw new Error(`Could not register Telepathy client. Error: ${e}`);
}
if (!this._client.account_manager.is_prepared(Tp.AccountManager.get_feature_quark_core()))
@ -149,20 +147,20 @@ class TelepathyClient extends Tp.BaseClient {
this._delegatedChannelsCb.bind(this));
}
vfunc_observe_channels(account, conn, channels,
dispatchOp, requests, context) {
vfunc_observe_channels(...args) {
let [account, conn, channels, dispatchOp, requests, context] = args;
let len = channels.length;
for (let i = 0; i < len; i++) {
let channel = channels[i];
let [targetHandle, targetHandleType] = channel.get_handle();
if (channel.get_invalidated())
continue;
continue;
/* Only observe contact text channels */
if ((!(channel instanceof Tp.TextChannel)) ||
targetHandleType != Tp.HandleType.CONTACT)
continue;
continue;
this._createChatSource(account, conn, channel, channel.get_target_contact());
}
@ -182,8 +180,8 @@ class TelepathyClient extends Tp.BaseClient {
});
}
vfunc_handle_channels(account, conn, channels, requests,
user_action_time, context) {
vfunc_handle_channels(...args) {
let [account, conn, channels, requests, userActionTime, context] = args;
this._handlingChannels(account, conn, channels, true);
context.accept();
}
@ -200,7 +198,7 @@ class TelepathyClient extends Tp.BaseClient {
}
if (channel.get_invalidated())
continue;
continue;
// 'notify' will be true when coming from an actual HandleChannels
// call, and not when from a successful Claim call. The point is
@ -222,8 +220,8 @@ class TelepathyClient extends Tp.BaseClient {
}
}
vfunc_add_dispatch_operation(account, conn, channels,
dispatchOp, context) {
vfunc_add_dispatch_operation(...args) {
let [account, conn, channels, dispatchOp, context] = args;
let channel = channels[0];
let chanType = channel.get_channel_type();
@ -255,7 +253,7 @@ class TelepathyClient extends Tp.BaseClient {
dispatchOp.claim_with_finish(result);
this._handlingChannels(account, conn, [channel], false);
} catch (err) {
log('Failed to Claim channel: ' + err);
log(`Failed to Claim channel: ${err}`);
}
});
@ -362,28 +360,28 @@ var ChatSource = class extends MessageTray.Source {
let presenceType = this._contact.get_presence_type();
switch (presenceType) {
case Tp.ConnectionPresenceType.AVAILABLE:
iconName = 'user-available';
break;
case Tp.ConnectionPresenceType.BUSY:
iconName = 'user-busy';
break;
case Tp.ConnectionPresenceType.OFFLINE:
iconName = 'user-offline';
break;
case Tp.ConnectionPresenceType.HIDDEN:
iconName = 'user-invisible';
break;
case Tp.ConnectionPresenceType.AWAY:
iconName = 'user-away';
break;
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
iconName = 'user-idle';
break;
default:
iconName = 'user-offline';
}
return new Gio.ThemedIcon({ name: iconName });
case Tp.ConnectionPresenceType.AVAILABLE:
iconName = 'user-available';
break;
case Tp.ConnectionPresenceType.BUSY:
iconName = 'user-busy';
break;
case Tp.ConnectionPresenceType.OFFLINE:
iconName = 'user-offline';
break;
case Tp.ConnectionPresenceType.HIDDEN:
iconName = 'user-invisible';
break;
case Tp.ConnectionPresenceType.AWAY:
iconName = 'user-away';
break;
case Tp.ConnectionPresenceType.EXTENDED_AWAY:
iconName = 'user-idle';
break;
default:
iconName = 'user-offline';
}
return new Gio.ThemedIcon({ name: iconName });
}
_updateAvatarIcon() {
@ -597,8 +595,8 @@ var ChatSource = class extends MessageTray.Source {
// keep track of it with the ChatStateChanged signal but it is good
// enough right now.
if (state != this._chatState) {
this._chatState = state;
this._channel.set_chat_state_async(state, null);
this._chatState = state;
this._channel.set_chat_state_async(state, null);
}
}

View File

@ -7,7 +7,6 @@ const SwitcherPopup = imports.ui.switcherPopup;
const Params = imports.misc.params;
var POPUP_APPICON_SIZE = 96;
var POPUP_FADE_TIME = 0.1; // seconds
var SortGroup = {
TOP: 0,
@ -33,7 +32,7 @@ var CtrlAltTabManager = class CtrlAltTabManager {
item.iconName = icon;
this._items.push(item);
root.connect('destroy', () => { this.removeGroup(root); });
root.connect('destroy', () => this.removeGroup(root));
if (root instanceof St.Widget)
global.focus_manager.add_group(root);
}

View File

@ -35,7 +35,7 @@ class DashItemContainer extends St.Widget {
x_align: Clutter.ActorAlign.CENTER });
this._labelText = "";
this.label = new St.Label({ style_class: 'dash-label'});
this.label = new St.Label({ style_class: 'dash-label' });
this.label.hide();
Main.layoutManager.addChrome(this.label);
this.label_actor = this.label;
@ -81,7 +81,7 @@ class DashItemContainer extends St.Widget {
let itemHeight = this.allocation.y2 - this.allocation.y1;
let labelHeight = this.label.get_height();
let yOffset = Math.floor((itemHeight - labelHeight) / 2)
let yOffset = Math.floor((itemHeight - labelHeight) / 2);
let y = stageY + yOffset;
@ -198,9 +198,9 @@ class ShowAppsIcon extends DashItemContainer {
toggle_mode: true });
this._iconActor = null;
this.icon = new IconGrid.BaseIcon(_("Show Applications"),
{ setSizeManually: true,
showLabel: false,
createIcon: this._createIcon.bind(this) });
{ setSizeManually: true,
showLabel: false,
createIcon: this._createIcon.bind(this) });
this.toggleButton.add_actor(this.icon);
this.toggleButton._delegate = this;
@ -321,14 +321,14 @@ class DashActor extends St.Widget {
let themeNode = this.get_theme_node();
let adjustedForWidth = themeNode.adjust_for_width(forWidth);
let [, showAppsButton] = this.get_children();
let [minHeight, ] = showAppsButton.get_preferred_height(adjustedForWidth);
[minHeight, ] = themeNode.adjust_preferred_height(minHeight, natHeight);
let [minHeight] = showAppsButton.get_preferred_height(adjustedForWidth);
[minHeight] = themeNode.adjust_preferred_height(minHeight, natHeight);
return [minHeight, natHeight];
}
});
const baseIconSizes = [ 16, 22, 24, 32, 48, 64 ];
const baseIconSizes = [16, 22, 24, 32, 48, 64];
var Dash = class Dash {
constructor() {
@ -648,10 +648,10 @@ var Dash = class Dash {
let running = this._appSystem.get_running();
let children = this._box.get_children().filter(actor => {
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
});
return actor.child &&
actor.child._delegate &&
actor.child._delegate.app;
});
// Apps currently in the dash
let oldApps = children.map(actor => actor.child._delegate.app);
// Apps supposed to be in the dash
@ -700,14 +700,14 @@ var Dash = class Dash {
}
// App removed at oldIndex
if (oldApp && newApps.indexOf(oldApp) == -1) {
if (oldApp && !newApps.includes(oldApp)) {
removedActors.push(children[oldIndex]);
oldIndex++;
continue;
}
// App added at newIndex
if (newApp && oldApps.indexOf(newApp) == -1) {
if (newApp && !oldApps.includes(newApp)) {
addedItems.push({ app: newApp,
item: this._createAppItem(newApp),
pos: newIndex });

View File

@ -47,7 +47,7 @@ var TodayButton = class TodayButton {
this._calendar.connect('selected-date-changed', (calendar, date) => {
// Make the button reactive only if the selected date is not the
// current date.
this.actor.reactive = !_isToday(date)
this.actor.reactive = !_isToday(date);
});
}
@ -217,7 +217,7 @@ var WeatherSection = class WeatherSection {
});
let box = new St.BoxLayout({ style_class: 'weather-box',
vertical: true });
vertical: true });
this.actor.child = box;
@ -357,7 +357,7 @@ var MessagesIndicator = class MessagesIndicator {
Main.messageTray.connect('queue-changed', this._updateCount.bind(this));
let sources = Main.messageTray.getSources();
sources.forEach(source => { this._onSourceAdded(null, source); });
sources.forEach(source => this._onSourceAdded(null, source));
}
_onSourceAdded(tray, source) {
@ -373,7 +373,7 @@ var MessagesIndicator = class MessagesIndicator {
_updateCount() {
let count = 0;
this._sources.forEach(source => { count += source.unseenCount; });
this._sources.forEach(source => count += source.unseenCount);
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);
@ -384,8 +384,8 @@ var IndicatorPad = GObject.registerClass(
class IndicatorPad extends St.Widget {
_init(actor) {
this._source = actor;
this._source.connect('notify::visible', () => { this.queue_relayout(); });
this._source.connect('notify::size', () => { this.queue_relayout(); });
this._source.connect('notify::visible', () => this.queue_relayout());
this._source.connect('notify::size', () => this.queue_relayout());
super._init();
}
@ -459,7 +459,6 @@ class CalendarColumnLayout extends Clutter.BoxLayout {
var DateMenuButton = GObject.registerClass(
class DateMenuButton extends PanelMenu.Button {
_init() {
let item;
let hbox;
let vbox;

View File

@ -25,9 +25,9 @@ class Dialog extends St.Widget {
_createDialog() {
this._dialog = new St.BoxLayout({ style_class: 'modal-dialog',
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
vertical: true });
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER,
vertical: true });
// modal dialogs are fixed width and grow vertically; set the request
// mode accordingly so wrapped labels are handled correctly during
@ -38,13 +38,13 @@ class Dialog extends St.Widget {
this.contentLayout = new St.BoxLayout({ vertical: true,
style_class: "modal-dialog-content-box" });
this._dialog.add(this.contentLayout,
{ expand: true,
x_fill: true,
y_fill: true,
{ expand: true,
x_fill: true,
y_fill: true,
x_align: St.Align.MIDDLE,
y_align: St.Align.START });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous:true }) });
this.buttonLayout = new St.Widget ({ layout_manager: new Clutter.BoxLayout({ homogeneous: true }) });
this._dialog.add(this.buttonLayout,
{ x_align: St.Align.MIDDLE,
y_align: St.Align.START });
@ -116,11 +116,11 @@ class Dialog extends St.Widget {
let button = new St.Button({ style_class: 'modal-dialog-linked-button',
button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE,
reactive: true,
can_focus: true,
x_expand: true,
y_expand: true,
label: label });
reactive: true,
can_focus: true,
x_expand: true,
y_expand: true,
label: label });
button.connect('clicked', action);
buttonInfo['button'] = button;
@ -180,10 +180,8 @@ var MessageDialogContent = GObject.registerClass({
this._subtitle.clutter_text.set(textProps);
this._body.clutter_text.set(textProps);
if (!params.hasOwnProperty('style_class'))
params.style_class = 'message-dialog-main-layout';
super._init(params);
let defaultParams = { style_class: 'message-dialog-main-layout' };
super._init(Object.assign(defaultParams, params));
this.messageBox = new St.BoxLayout({ style_class: 'message-dialog-content',
x_expand: true,
@ -214,7 +212,10 @@ var MessageDialogContent = GObject.registerClass({
}
set icon(icon) {
Object.assign(this._icon, { gicon: icon, visible: icon != null });
this._icon.set({
gicon: icon,
visible: icon != null
});
this.notify('icon');
}
@ -231,7 +232,10 @@ var MessageDialogContent = GObject.registerClass({
}
_setLabel(label, prop, value) {
Object.assign(label, { text: value || '', visible: value != null });
label.set({
text: value || '',
visible: value != null
});
this.notify(prop);
}

View File

@ -434,14 +434,13 @@ var _Draggable = class _Draggable {
scale_y: scale * origScale,
time: SCALE_ANIMATION_TIME,
transition: 'easeOutQuad',
onUpdate() {
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);
},
onUpdateScope: this });
} });
}
}
}
@ -561,11 +560,11 @@ var _Draggable = class _Draggable {
let dropFunc = dragMonitors[i].dragDrop;
if (dropFunc)
switch (dropFunc(dropEvent)) {
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
case DragDropResult.FAILURE:
case DragDropResult.SUCCESS:
return true;
case DragDropResult.CONTINUE:
continue;
}
}
@ -588,8 +587,9 @@ var _Draggable = class _Draggable {
if (this._restoreOnSuccess) {
this._restoreDragActor(event.get_time());
return true;
} else
} else {
this._dragActor.destroy();
}
}
this._dragState = DragState.INIT;
@ -689,12 +689,12 @@ var _Draggable = class _Draggable {
params['onCompleteParams'] = [this._dragActor, eventTime];
// start the animation
Tweener.addTween(this._dragActor, params)
Tweener.addTween(this._dragActor, params);
}
_finishAnimation() {
if (!this._animationInProgress)
return
return;
this._animationInProgress = false;
if (!this._buttonDown)

View File

@ -16,7 +16,7 @@ var EdgeDragAction = GObject.registerClass({
this._allowedModes = allowedModes;
this.set_n_touch_points(1);
global.display.connect('grab-op-begin', () => { this.cancel(); });
global.display.connect('grab-op-begin', () => this.cancel());
}
_getMonitorRect(x, y) {

View File

@ -19,7 +19,7 @@
const Mainloop = imports.mainloop;
const { AccountsService, Clutter, Gio,
GLib, Pango, Polkit, Shell, St } = imports.gi;
GLib, GObject, Pango, Polkit, Shell, St } = imports.gi;
const CheckBox = imports.ui.checkBox;
const GnomeSession = imports.misc.gnomeSession;
@ -29,13 +29,9 @@ const UserWidget = imports.ui.userWidget;
const { loadInterfaceXML } = imports.misc.fileUtils;
let _endSessionDialog = null;
const _ITEM_ICON_SIZE = 48;
const _DIALOG_ICON_SIZE = 48;
var GSM_SESSION_MANAGER_LOGOUT_FORCE = 2;
const EndSessionDialogIface = loadInterfaceXML('org.gnome.SessionManager.EndSessionDialog');
const logoutDialogContent = {
@ -53,7 +49,7 @@ const logoutDialogContent = {
},
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedLogout',
label: C_("button", "Log Out") }],
label: C_("button", "Log Out") }],
iconStyleClass: 'end-session-dialog-logout-icon',
showOtherSessions: false,
};
@ -69,9 +65,9 @@ const shutdownDialogContent = {
checkBoxText: C_("checkbox", "Install pending software updates"),
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") },
label: C_("button", "Restart") },
{ signal: 'ConfirmedShutdown',
label: C_("button", "Power Off") }],
label: C_("button", "Power Off") }],
iconName: 'system-shutdown-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
@ -86,7 +82,7 @@ const restartDialogContent = {
},
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart") }],
label: C_("button", "Restart") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
@ -102,7 +98,7 @@ const restartUpdateDialogContent = {
},
showBatteryWarning: true,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
label: C_("button", "Restart &amp; Install") }],
unusedFutureButtonForTranslation: C_("button", "Install &amp; Power Off"),
unusedFutureCheckBoxForTranslation: C_("checkbox", "Power off after updates are installed"),
iconName: 'view-refresh-symbolic',
@ -122,18 +118,18 @@ const restartUpgradeDialogContent = {
disableTimer: true,
showBatteryWarning: false,
confirmButtons: [{ signal: 'ConfirmedReboot',
label: C_("button", "Restart &amp; Install") }],
label: C_("button", "Restart &amp; Install") }],
iconName: 'view-refresh-symbolic',
iconStyleClass: 'end-session-dialog-shutdown-icon',
showOtherSessions: true,
};
const DialogType = {
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3,
UPGRADE_RESTART: 4
LOGOUT: 0 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT */,
SHUTDOWN: 1 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN */,
RESTART: 2 /* GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART */,
UPDATE_RESTART: 3,
UPGRADE_RESTART: 4
};
const DialogContent = {
@ -159,7 +155,7 @@ function findAppFromInhibitor(inhibitor) {
let desktopFile;
try {
[desktopFile] = inhibitor.GetAppIdSync();
} catch(e) {
} catch (e) {
// XXX -- sometimes JIT inhibitors generated by gnome-session
// get removed too soon. Don't fail in this case.
log('gnome-session gave us a dead inhibitor: %s'.format(inhibitor.get_object_path()));
@ -223,25 +219,25 @@ function init() {
// This always returns the same singleton object
// By instantiating it initially, we register the
// bus object, etc.
_endSessionDialog = new EndSessionDialog();
(new EndSessionDialog());
}
var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
constructor() {
super({ styleClass: 'end-session-dialog',
destroyOnClose: false });
var EndSessionDialog = GObject.registerClass(
class EndSessionDialog extends ModalDialog.ModalDialog {
_init() {
super._init({ styleClass: 'end-session-dialog',
destroyOnClose: false });
this._loginManager = LoginManager.getLoginManager();
this._userManager = AccountsService.UserManager.get_default();
this._user = this._userManager.get_user(GLib.get_user_name());
this._updatesPermission = null;
this._pkOfflineProxy = new PkOfflineProxy(Gio.DBus.system,
'org.freedesktop.PackageKit',
'/org/freedesktop/PackageKit',
(proxy, error) => {
if (error)
log(error.message);
});
this._onPkOfflineProxyCreated.bind(this));
this._powerProxy = new UPowerProxy(Gio.DBus.system,
'org.freedesktop.UPower',
'/org/freedesktop/UPower',
@ -275,8 +271,8 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
this._iconBin = new St.Bin();
mainContentLayout.add(this._iconBin,
{ x_fill: true,
y_fill: false,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
@ -289,7 +285,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
messageLayout.add(this._subjectLabel,
{ x_fill: false,
y_fill: false,
y_fill: false,
x_align: St.Align.START,
y_align: St.Align.START });
@ -298,7 +294,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
this._descriptionLabel.clutter_text.line_wrap = true;
messageLayout.add(this._descriptionLabel,
{ y_fill: true,
{ y_fill: true,
y_align: St.Align.START });
this._checkBox = new CheckBox.CheckBox();
@ -336,16 +332,33 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
this._inhibitorSection.add_actor(this._sessionHeader);
this._inhibitorSection.add_actor(this._sessionList);
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()));
}
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(EndSessionDialogIface, this);
this._dbusImpl.export(Gio.DBus.session, '/org/gnome/SessionManager/EndSessionDialog');
}
_onPkOfflineProxyCreated(proxy, error) {
if (error) {
log(error.message);
return;
}
// Creating a D-Bus proxy won't propagate SERVICE_UNKNOWN or NAME_HAS_NO_OWNER
// errors if PackageKit is not available, but the GIO implementation will make
// sure in that case that the proxy's g-name-owner is set to null, so check that.
if (this._pkOfflineProxy.g_name_owner === null) {
this._pkOfflineProxy = null;
return;
}
// 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()));
}
}
_onDestroy() {
this._user.disconnect(this._userLoadedId);
this._user.disconnect(this._userChangedId);
@ -390,7 +403,8 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
}
// Use a different description when we are installing a system upgrade
if (dialogContent.upgradeDescription) {
// if the PackageKit proxy is available (i.e. PackageKit is available).
if (this._pkOfflineProxy && dialogContent.upgradeDescription) {
let name = this._pkOfflineProxy.PreparedUpgrade['name'].deep_unpack();
let version = this._pkOfflineProxy.PreparedUpgrade['version'].deep_unpack();
@ -427,8 +441,8 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
_updateButtons() {
let dialogContent = DialogContent[this._type];
let buttons = [{ action: this.cancel.bind(this),
label: _("Cancel"),
key: Clutter.Escape }];
label: _("Cancel"),
key: Clutter.Escape }];
for (let i = 0; i < dialogContent.confirmButtons.length; i++) {
let signal = dialogContent.confirmButtons[i].signal;
@ -475,19 +489,19 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
// Trigger the offline update as requested
if (this._checkBox.actor.checked) {
switch (signal) {
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
break;
case "ConfirmedShutdown":
// To actually trigger the offline update, we need to
// reboot to do the upgrade. When the upgrade is complete,
// the computer will shut down automatically.
signal = "ConfirmedReboot";
this._triggerOfflineUpdateShutdown(callback);
break;
default:
callback();
break;
case "ConfirmedReboot":
this._triggerOfflineUpdateReboot(callback);
break;
case "ConfirmedShutdown":
// To actually trigger the offline update, we need to
// reboot to do the upgrade. When the upgrade is complete,
// the computer will shut down automatically.
signal = "ConfirmedReboot";
this._triggerOfflineUpdateShutdown(callback);
break;
default:
callback();
break;
}
} else {
this._triggerOfflineUpdateCancel(callback);
@ -499,6 +513,12 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateReboot(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.TriggerRemote('reboot', (result, error) => {
if (error)
log(error.message);
@ -508,6 +528,12 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateShutdown(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.TriggerRemote('power-off', (result, error) => {
if (error)
log(error.message);
@ -517,6 +543,12 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
}
_triggerOfflineUpdateCancel(callback) {
// Handle this gracefully if PackageKit is not available.
if (!this._pkOfflineProxy) {
callback();
return;
}
this._pkOfflineProxy.CancelRemote((result, error) => {
if (error)
log(error.message);
@ -584,7 +616,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
}
_onInhibitorLoaded(inhibitor) {
if (this._applications.indexOf(inhibitor) < 0) {
if (!this._applications.includes(inhibitor)) {
// Stale inhibitor
return;
}
@ -636,7 +668,7 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
this._loginManager.listSessions(result => {
let n = 0;
for (let i = 0; i < result.length; i++) {
let[id, uid, userName, seat, sessionPath] = result[i];
let [id, uid, userName, seat, sessionPath] = result[i];
let proxy = new LogindSession(Gio.DBus.system, 'org.freedesktop.login1', sessionPath);
if (proxy.Class != 'user')
@ -679,7 +711,8 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
this._totalSecondsToStayOpen = totalSecondsToStayOpen;
this._type = type;
if (this._type == DialogType.RESTART) {
// Only consider updates and upgrades if PackageKit is available.
if (this._pkOfflineProxy && this._type == DialogType.RESTART) {
if (this._pkOfflineProxy.UpdateTriggered)
this._type = DialogType.UPDATE_RESTART;
else if (this._pkOfflineProxy.UpgradeTriggered)
@ -711,8 +744,9 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
if (dialogContent.showOtherSessions)
this._loadSessions();
let updateTriggered = this._pkOfflineProxy.UpdateTriggered;
let updatePrepared = this._pkOfflineProxy.UpdatePrepared;
// Only consider updates and upgrades if PackageKit is available.
let updateTriggered = this._pkOfflineProxy ? this._pkOfflineProxy.UpdateTriggered : false;
let updatePrepared = this._pkOfflineProxy ? this._pkOfflineProxy.UpdatePrepared : false;
let updatesAllowed = this._updatesPermission && this._updatesPermission.allowed;
_setCheckBoxLabel(this._checkBox, dialogContent.checkBoxText || '');
@ -747,4 +781,4 @@ var EndSessionDialog = class EndSessionDialog extends ModalDialog.ModalDialog {
Close(parameters, invocation) {
this.close();
}
};
});

View File

@ -57,8 +57,8 @@ function _patchLayoutClass(layoutClass, styleProps) {
};
}
function _loggingFunc() {
let fields = {'MESSAGE': [].join.call(arguments, ', ')};
function _loggingFunc(...args) {
let fields = { 'MESSAGE': args.join(', ') };
let domain = "GNOME Shell";
// If the caller is an extension, add it as metadata
@ -111,10 +111,10 @@ function init() {
let base = origToString.call(this);
try {
if ('actor' in this && this.actor instanceof Clutter.Actor)
return base.replace(/\]$/, ' delegate for ' + this.actor.toString().substring(1));
return base.replace(/\]$/, ` delegate for ${this.actor.toString().substring(1)}`);
else
return base;
} catch(e) {
} catch (e) {
return base;
}
};

View File

@ -1,19 +1,18 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, Soup, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Soup } = imports.gi;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const ExtensionUtils = imports.misc.extensionUtils;
const ExtensionSystem = imports.ui.extensionSystem;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
const _signals = ExtensionSystem._signals;
var REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
var REPOSITORY_URL_DOWNLOAD = REPOSITORY_URL_BASE + '/download-extension/%s.shell-extension.zip';
var REPOSITORY_URL_INFO = REPOSITORY_URL_BASE + '/extension-info/';
var REPOSITORY_URL_UPDATE = REPOSITORY_URL_BASE + '/update-info/';
var REPOSITORY_URL_DOWNLOAD = `${REPOSITORY_URL_BASE}/download-extension/%s.shell-extension.zip`;
var REPOSITORY_URL_INFO = `${REPOSITORY_URL_BASE}/extension-info/`;
var REPOSITORY_URL_UPDATE = `${REPOSITORY_URL_BASE}/update-info/`;
let _httpSession;
@ -25,7 +24,7 @@ function installExtension(uuid, invocation) {
_httpSession.queue_message(message, (session, message) => {
if (message.status_code != Soup.KnownStatusCode.OK) {
ExtensionSystem.logExtensionError(uuid, 'downloading info: ' + message.status_code);
Main.extensionManager.logExtensionError(uuid, `downloading info: ${message.status_code}`);
invocation.return_dbus_error('org.gnome.Shell.DownloadInfoError', message.status_code.toString());
return;
}
@ -34,7 +33,7 @@ function installExtension(uuid, invocation) {
try {
info = JSON.parse(message.response_body.data);
} catch (e) {
ExtensionSystem.logExtensionError(uuid, 'parsing info: ' + e);
Main.extensionManager.logExtensionError(uuid, `parsing info: ${e}`);
invocation.return_dbus_error('org.gnome.Shell.ParseInfoError', e.toString());
return;
}
@ -45,7 +44,7 @@ function installExtension(uuid, invocation) {
}
function uninstallExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let extension = Main.extensionManager.lookup(uuid);
if (!extension)
return false;
@ -53,7 +52,7 @@ function uninstallExtension(uuid) {
if (extension.type != ExtensionUtils.ExtensionType.PER_USER)
return false;
if (!ExtensionSystem.unloadExtension(extension))
if (!Main.extensionManager.unloadExtension(extension))
return false;
FileUtils.recursivelyDeleteDir(extension.dir, true);
@ -114,10 +113,10 @@ function updateExtension(uuid) {
_httpSession.queue_message(message, (session, message) => {
gotExtensionZipFile(session, message, uuid, newExtensionTmpDir, () => {
let oldExtension = ExtensionUtils.extensions[uuid];
let oldExtension = Main.extensionManager.lookup(uuid);
let extensionDir = oldExtension.dir;
if (!ExtensionSystem.unloadExtension(oldExtension))
if (!Main.extensionManager.unloadExtension(oldExtension))
return;
FileUtils.recursivelyMoveDir(extensionDir, oldExtensionTmpDir);
@ -126,11 +125,11 @@ function updateExtension(uuid) {
let extension = null;
try {
extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
} catch(e) {
extension = Main.extensionManager.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension);
} catch (e) {
if (extension)
ExtensionSystem.unloadExtension(extension);
Main.extensionManager.unloadExtension(extension);
logError(e, 'Error loading extension %s'.format(uuid));
@ -139,7 +138,7 @@ function updateExtension(uuid) {
// Restore what was there before. We can't do much if we
// fail here.
ExtensionSystem.loadExtension(oldExtension);
Main.extensionManager.loadExtension(oldExtension);
return;
}
@ -152,9 +151,9 @@ function updateExtension(uuid) {
function checkForUpdates() {
let metadatas = {};
for (let uuid in ExtensionUtils.extensions) {
metadatas[uuid] = ExtensionUtils.extensions[uuid].metadata;
}
Main.extensionManager.getUuids().forEach(uuid => {
metadatas[uuid] = Main.extensionManager.extensions[uuid].metadata;
});
let params = { shell_version: Config.PACKAGE_VERSION,
installed: JSON.stringify(metadatas) };
@ -176,10 +175,10 @@ function checkForUpdates() {
});
}
var InstallExtensionDialog =
var InstallExtensionDialog = GObject.registerClass(
class InstallExtensionDialog extends ModalDialog.ModalDialog {
constructor(uuid, info, invocation) {
super({ styleClass: 'extension-dialog' });
_init(uuid, info, invocation) {
super._init({ styleClass: 'extension-dialog' });
this._uuid = uuid;
this._info = info;
@ -187,26 +186,21 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.setButtons([{ label: _("Cancel"),
action: this._onCancelButtonPressed.bind(this),
key: Clutter.Escape
key: Clutter.Escape
},
{ label: _("Install"),
{ label: _("Install"),
action: this._onInstallButtonPressed.bind(this),
default: true
}]);
let message = _("Download and install “%s” from extensions.gnome.org?").format(info.name);
let content = new Dialog.MessageDialogContent({
title: _("Download and install “%s” from extensions.gnome.org?").format(info.name),
icon: new Gio.FileIcon({
file: Gio.File.new_for_uri(`${REPOSITORY_URL_BASE}${info.icon}`)
})
});
let box = new St.BoxLayout({ style_class: 'message-dialog-main-layout',
vertical: false });
this.contentLayout.add(box);
let gicon = new Gio.FileIcon({ file: Gio.File.new_for_uri(REPOSITORY_URL_BASE + info.icon) })
let icon = new St.Icon({ gicon: gicon });
box.add(icon);
let label = new St.Label({ style_class: 'message-dialog-title headline',
text: message });
box.add(label);
this.contentLayout.add(content);
}
_onCancelButtonPressed(button, event) {
@ -226,21 +220,16 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
function errback(code, message) {
let msg = message ? message.toString() : '';
log('Error while installing %s: %s (%s)'.format(uuid, code, msg));
invocation.return_dbus_error('org.gnome.Shell.' + code, msg);
invocation.return_dbus_error(`org.gnome.Shell.${code}`, msg);
}
function callback() {
// Add extension to 'enabled-extensions' for the user, always...
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
if (enabledExtensions.indexOf(uuid) == -1) {
enabledExtensions.push(uuid);
global.settings.set_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
try {
let extension = ExtensionUtils.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
} catch(e) {
let extension = Main.extensionManager.createExtensionObject(uuid, dir, ExtensionUtils.ExtensionType.PER_USER);
Main.extensionManager.loadExtension(extension);
if (!Main.extensionManager.enableExtension(uuid))
throw new Error(`Cannot add ${uuid} to enabled extensions gsettings key`);
} catch (e) {
uninstallExtension(uuid);
errback('LoadExtensionError', e);
return;
@ -255,7 +244,7 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.close();
}
};
});
function init() {
_httpSession = new Soup.SessionAsync({ ssl_use_system_ca_file: true });

View File

@ -4,371 +4,519 @@ const { Gio, St } = imports.gi;
const Signals = imports.signals;
const ExtensionUtils = imports.misc.extensionUtils;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
var ExtensionState = {
ENABLED: 1,
DISABLED: 2,
ERROR: 3,
OUT_OF_DATE: 4,
DOWNLOADING: 5,
INITIALIZED: 6,
// Used as an error state for operations on unknown extensions,
// should never be in a real extensionMeta object.
UNINSTALLED: 99
};
// Arrays of uuids
var enabledExtensions;
// Contains the order that extensions were enabled in.
var extensionOrder = [];
// We don't really have a class to add signals on. So, create
// a simple dummy object, add the signal methods, and export those
// publically.
var _signals = {};
Signals.addSignalMethods(_signals);
var connect = _signals.connect.bind(_signals);
var disconnect = _signals.disconnect.bind(_signals);
const { ExtensionState, ExtensionType } = ExtensionUtils;
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
const DISABLED_EXTENSIONS_KEY = 'disabled-extensions';
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
var initted = false;
var enabled;
var ExtensionManager = class {
constructor() {
this._initted = false;
this._enabled = false;
function disableExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
this._extensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
if (extension.state != ExtensionState.ENABLED)
return;
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
}
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
init() {
this._sessionUpdated();
}
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
lookup(uuid) {
return this._extensions.get(uuid);
}
let orderIdx = extensionOrder.indexOf(uuid);
let order = extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
getUuids() {
return [...this._extensions.keys()];
}
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
ExtensionUtils.extensions[uuid].stateObj.disable();
} catch(e) {
logExtensionError(uuid, e);
_callExtensionDisable(uuid) {
let extension = this.lookup(uuid);
if (!extension)
return;
if (extension.state != ExtensionState.ENABLED)
return;
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
let orderIdx = this._extensionOrder.indexOf(uuid);
let order = this._extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
this.lookup(uuid).stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
}
}
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
try {
extension.stateObj.disable();
} catch(e) {
logExtensionError(uuid, e);
}
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
try {
ExtensionUtils.extensions[uuid].stateObj.enable();
} catch(e) {
logExtensionError(uuid, e);
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
}
extensionOrder.splice(orderIdx, 1);
if ( extension.state != ExtensionState.ERROR ) {
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-state-changed', extension);
}
}
function enableExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
if (extension.state == ExtensionState.INITIALIZED)
initExtension(uuid);
if (extension.state != ExtensionState.DISABLED)
return;
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++) {
try {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile;
break;
extension.stateObj.disable();
} 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);
}
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
try {
this.lookup(uuid).stateObj.enable();
} catch (e) {
this.logExtensionError(uuid, e);
}
}
this._extensionOrder.splice(orderIdx, 1);
if (extension.state != ExtensionState.ERROR) {
extension.state = ExtensionState.DISABLED;
this.emit('extension-state-changed', extension);
}
}
_callExtensionEnable(uuid) {
let extension = this.lookup(uuid);
if (!extension)
return;
if (extension.state == ExtensionState.INITIALIZED)
this._callExtensionInit(uuid);
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++) {
try {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile;
break;
} 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}`);
return;
}
}
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
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;
}
}
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
_signals.emit('extension-state-changed', extension);
return;
} catch(e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
enableExtension(uuid) {
if (!this._extensions.has(uuid))
return false;
let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY);
if (disabledExtensions.includes(uuid)) {
disabledExtensions = disabledExtensions.filter(item => item !== uuid);
global.settings.set_strv(DISABLED_EXTENSIONS_KEY, disabledExtensions);
}
logExtensionError(uuid, e);
return;
}
}
function logExtensionError(uuid, error) {
let extension = ExtensionUtils.extensions[uuid];
if (!extension)
return;
let message = '' + error;
extension.state = ExtensionState.ERROR;
if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message));
_signals.emit('extension-state-changed', { uuid: uuid,
error: message,
state: extension.state });
}
function loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else {
let enabled = enabledExtensions.indexOf(extension.uuid) != -1;
if (enabled) {
if (!initExtension(extension.uuid))
return;
if (extension.state == ExtensionState.DISABLED)
enableExtension(extension.uuid);
} else {
extension.state = ExtensionState.INITIALIZED;
if (!enabledExtensions.includes(uuid)) {
enabledExtensions.push(uuid);
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
return true;
}
_signals.emit('extension-state-changed', extension);
}
disableExtension(uuid) {
if (!this._extensions.has(uuid))
return false;
function unloadExtension(extension) {
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
disableExtension(extension.uuid);
let enabledExtensions = global.settings.get_strv(ENABLED_EXTENSIONS_KEY);
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY);
extension.state = ExtensionState.UNINSTALLED;
_signals.emit('extension-state-changed', extension);
if (enabledExtensions.includes(uuid)) {
enabledExtensions = enabledExtensions.filter(item => item !== uuid);
global.settings.set_strv(ENABLED_EXTENSIONS_KEY, enabledExtensions);
}
delete ExtensionUtils.extensions[extension.uuid];
return true;
}
if (!disabledExtensions.includes(uuid)) {
disabledExtensions.push(uuid);
global.settings.set_strv(DISABLED_EXTENSIONS_KEY, disabledExtensions);
}
function reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
// Then unload the old extension.
unloadExtension(oldExtension);
// Now, recreate the extension and load it.
let newExtension;
try {
newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
} catch(e) {
logExtensionError(uuid, e);
return;
return true;
}
loadExtension(newExtension);
}
logExtensionError(uuid, error) {
let extension = this.lookup(uuid);
if (!extension)
return;
function initExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let dir = extension.dir;
let message = `${error}`;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
extension.error = message;
extension.state = ExtensionState.ERROR;
if (!extension.errors)
extension.errors = [];
extension.errors.push(message);
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
logExtensionError(uuid, new Error('Missing extension.js'));
return false;
log('Extension "%s" had error: %s'.format(uuid, message));
this.emit('extension-state-changed', extension);
}
let extensionModule;
let extensionState = null;
createExtensionObject(uuid, dir, type) {
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
ExtensionUtils.installImporter(extension);
try {
extensionModule = extension.imports.extension;
} catch(e) {
logExtensionError(uuid, e);
return false;
}
if (extensionModule.init) {
let metadataContents, success;
try {
extensionState = extensionModule.init(extension);
} catch(e) {
logExtensionError(uuid, e);
[success, metadataContents] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) {
throw new Error(`Failed to load metadata.json: ${e}`);
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error(`Failed to parse metadata.json: ${e}`);
}
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i];
if (!meta[prop]) {
throw new Error(`missing "${prop}" property in metadata.json`);
}
}
if (uuid != meta.uuid) {
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${uuid}"`);
}
let extension = {
metadata: meta,
uuid: meta.uuid,
type,
dir,
path: dir.get_path(),
error: '',
hasPrefs: dir.get_child('prefs.js').query_exists(null),
canChange: false
};
this._extensions.set(uuid, extension);
return extension;
}
loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
if (!this._callExtensionInit(extension.uuid))
return;
if (extension.state == ExtensionState.DISABLED)
this._callExtensionEnable(extension.uuid);
} else {
extension.state = ExtensionState.INITIALIZED;
}
}
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
unloadExtension(extension) {
// Try to disable it -- if it's ERROR'd, we can't guarantee that,
// but it will be removed on next reboot, and hopefully nothing
// broke too much.
this._callExtensionDisable(extension.uuid);
extension.state = ExtensionState.UNINSTALLED;
this.emit('extension-state-changed', extension);
this._extensions.delete(extension.uuid);
return true;
}
reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
// Then unload the old extension.
this.unloadExtension(oldExtension);
// Now, recreate the extension and load it.
let newExtension;
try {
newExtension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
this.logExtensionError(uuid, e);
return;
}
this.loadExtension(newExtension);
}
_callExtensionInit(uuid) {
let extension = this.lookup(uuid);
let dir = extension.dir;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
return false;
}
let extensionModule;
let extensionState = null;
ExtensionUtils.installImporter(extension);
try {
extensionModule = extension.imports.extension;
} catch (e) {
this.logExtensionError(uuid, e);
return false;
}
if (extensionModule.init) {
try {
extensionState = extensionModule.init(extension);
} catch (e) {
this.logExtensionError(uuid, e);
return false;
}
}
if (!extensionState)
extensionState = extensionModule;
extension.stateObj = extensionState;
extension.state = ExtensionState.DISABLED;
this.emit('extension-loaded', uuid);
return true;
}
if (!extensionState)
extensionState = extensionModule;
extension.stateObj = extensionState;
_getModeExtensions() {
if (Array.isArray(Main.sessionMode.enabledExtensions))
return Main.sessionMode.enabledExtensions;
return [];
}
extension.state = ExtensionState.DISABLED;
_signals.emit('extension-loaded', uuid);
return true;
}
_updateCanChange(extension) {
let hasError =
extension.state == ExtensionState.ERROR ||
extension.state == ExtensionState.OUT_OF_DATE;
function getEnabledExtensions() {
let extensions;
if (Array.isArray(Main.sessionMode.enabledExtensions))
extensions = Main.sessionMode.enabledExtensions;
else
extensions = [];
let isMode = this._getModeExtensions().includes(extension.uuid);
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
return extensions;
let changeKey = isMode
? DISABLE_USER_EXTENSIONS_KEY
: ENABLED_EXTENSIONS_KEY;
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
}
extension.canChange =
!hasError &&
global.settings.is_writable(changeKey) &&
(isMode || !modeOnly);
}
function onEnabledExtensionsChanged() {
let newEnabledExtensions = getEnabledExtensions();
_getEnabledExtensions() {
let extensions = this._getModeExtensions();
if (!enabled)
return;
if (!global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
extensions = extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
uuid => !enabledExtensions.includes(uuid)
).forEach(uuid => {
enableExtension(uuid);
});
// filter out 'disabled-extensions' which takes precedence
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY);
return extensions.filter(item => !disabledExtensions.includes(item));
}
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
disableExtension(uuid);
});
_onUserExtensionsEnabledChanged() {
this._onEnabledExtensionsChanged();
this._onSettingsWritableChanged();
}
enabledExtensions = newEnabledExtensions;
}
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
function _onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
enabledExtensions = [];
for (let uuid in ExtensionUtils.extensions)
reloadExtension(ExtensionUtils.extensions[uuid]);
enabledExtensions = getEnabledExtensions();
if (!this._enabled)
return;
if (Main.sessionMode.allowExtensions) {
enabledExtensions.forEach(uuid => {
enableExtension(uuid);
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
uuid => !this._enabledExtensions.includes(uuid)
).forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
}
function _loadExtensions() {
global.settings.connect('changed::' + ENABLED_EXTENSIONS_KEY, onEnabledExtensionsChanged);
global.settings.connect('changed::' + DISABLE_USER_EXTENSIONS_KEY, onEnabledExtensionsChanged);
global.settings.connect('changed::' + EXTENSION_DISABLE_VERSION_CHECK_KEY, _onVersionValidationChanged);
enabledExtensions = getEnabledExtensions();
let finder = new ExtensionUtils.ExtensionFinder();
finder.connect('extension-found', (finder, extension) => {
loadExtension(extension);
});
finder.scanExtensions();
}
function enableAllExtensions() {
if (enabled)
return;
if (!initted) {
_loadExtensions();
initted = true;
} else {
enabledExtensions.forEach(uuid => {
enableExtension(uuid);
// 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._callExtensionDisable(uuid);
});
this._enabledExtensions = newEnabledExtensions;
}
enabled = true;
}
function disableAllExtensions() {
if (!enabled)
return;
_onSettingsWritableChanged() {
for (let extension of this._extensions.values()) {
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
}
if (initted) {
extensionOrder.slice().reverse().forEach(uuid => {
disableExtension(uuid);
_onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
this._enabledExtensions = [];
// 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();
if (Main.sessionMode.allowExtensions) {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
}
_loadExtensions() {
global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`,
this._onEnabledExtensionsChanged.bind(this));
global.settings.connect(`changed::${DISABLED_EXTENSIONS_KEY}`,
this._onEnabledExtensionsChanged.bind(this));
global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`,
this._onUserExtensionsEnabledChanged.bind(this));
global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`,
this._onVersionValidationChanged.bind(this));
global.settings.connect(`writable-changed::${ENABLED_EXTENSIONS_KEY}`,
this._onSettingsWritableChanged.bind(this));
global.settings.connect(`writable-changed::${DISABLED_EXTENSIONS_KEY}`,
this._onSettingsWritableChanged.bind(this));
this._enabledExtensions = this._getEnabledExtensions();
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = this.lookup(uuid);
if (existing) {
log(`Extension ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`);
return;
}
let extension;
let type = dir.has_prefix(perUserDir)
? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
logError(e, `Could not load extension ${uuid}`);
return;
}
this.loadExtension(extension);
});
}
enabled = false;
}
_enableAllExtensions() {
if (this._enabled)
return;
function _sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (initted)
enabledExtensions = getEnabledExtensions();
enableAllExtensions();
} else {
disableAllExtensions();
if (!this._initted) {
this._loadExtensions();
this._initted = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
this._enabled = true;
}
}
function init() {
Main.sessionMode.connect('updated', _sessionUpdated);
_sessionUpdated();
}
_disableAllExtensions() {
if (!this._enabled)
return;
if (this._initted) {
this._extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
}
this._enabled = false;
}
_sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (this._initted)
this._enabledExtensions = this._getEnabledExtensions();
this._enableAllExtensions();
} else {
this._disableAllExtensions();
}
}
};
Signals.addSignalMethods(ExtensionManager.prototype);

View File

@ -49,15 +49,15 @@ var FocusCaretTracker = class FocusCaretTracker {
this._atspiInited = true;
}
return this._atspiInited;
return this._atspiInited;
}
registerFocusListener() {
if (!this._initAtspi() || this._focusListenerRegistered)
return;
this._atspiListener.register(STATECHANGED + ':focused');
this._atspiListener.register(STATECHANGED + ':selected');
this._atspiListener.register(`${STATECHANGED}:focused`);
this._atspiListener.register(`${STATECHANGED}:selected`);
this._focusListenerRegistered = true;
}
@ -73,8 +73,8 @@ var FocusCaretTracker = class FocusCaretTracker {
if (!this._focusListenerRegistered)
return;
this._atspiListener.deregister(STATECHANGED + ':focused');
this._atspiListener.deregister(STATECHANGED + ':selected');
this._atspiListener.deregister(`${STATECHANGED}:focused`);
this._atspiListener.deregister(`${STATECHANGED}:selected`);
this._focusListenerRegistered = false;
}

View File

@ -43,6 +43,9 @@ function _popGrabHelper(grabHelper) {
// call grab().
var GrabHelper = class GrabHelper {
constructor(owner, params) {
if (!(owner instanceof Clutter.Actor))
throw new Error('GrabHelper owner must be a Clutter.Actor');
this._owner = owner;
this._modalParams = params;
@ -84,7 +87,7 @@ var GrabHelper = class GrabHelper {
_isWithinGrabbedActor(actor) {
let currentActor = this.currentGrab.actor;
while (actor) {
if (this._actors.indexOf(actor) != -1)
if (this._actors.includes(actor))
return true;
if (actor == currentActor)
return true;

View File

@ -8,8 +8,8 @@ const Main = imports.ui.main;
var MAX_CANDIDATES_PER_PAGE = 16;
var DEFAULT_INDEX_LABELS = [ '1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f' ];
var DEFAULT_INDEX_LABELS = ['1', '2', '3', '4', '5', '6', '7', '8',
'9', '0', 'a', 'b', 'c', 'd', 'e', 'f'];
var CandidateArea = class CandidateArea {
constructor() {
@ -37,14 +37,14 @@ var CandidateArea = class CandidateArea {
this.actor.connect('scroll-event', (actor, event) => {
let direction = event.get_scroll_direction();
switch(direction) {
switch (direction) {
case Clutter.ScrollDirection.UP:
this.emit('cursor-up');
break;
case Clutter.ScrollDirection.DOWN:
this.emit('cursor-down');
break;
};
}
return Clutter.EVENT_PROPAGATE;
});
@ -181,7 +181,7 @@ var CandidatePopup = class CandidatePopup {
let window = global.display.focus_window.get_compositor_private();
this._setDummyCursorGeometry(window.x + x, window.y + y, w, h);
});
} catch(e) {
} catch (e) {
// Only recent IBus versions have support for this signal
// which is used for wayland clients. In order to work
// with older IBus versions we can silently ignore the
@ -235,7 +235,7 @@ var CandidatePopup = class CandidatePopup {
let indexes = [];
let indexLabel;
for (let i = 0; (indexLabel = lookupTable.get_label(i)); ++i)
indexes.push(indexLabel.get_text());
indexes.push(indexLabel.get_text());
Main.keyboard.resetSuggestions();

View File

@ -12,11 +12,11 @@ var MIN_ICON_SIZE = 16;
var EXTRA_SPACE_ANIMATION_TIME = 0.25;
var ANIMATION_TIME_IN = 0.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;
var ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2/3 * ANIMATION_TIME_OUT;
var ANIMATION_FADE_IN_TIME_FOR_ITEM = 1/4 * ANIMATION_TIME_IN;
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;
var ANIMATION_MAX_DELAY_OUT_FOR_ITEM = 2 / 3 * ANIMATION_TIME_OUT;
var ANIMATION_FADE_IN_TIME_FOR_ITEM = 1 / 4 * ANIMATION_TIME_IN;
var ANIMATION_BOUNCE_ICON_SCALE = 1.1;
@ -141,7 +141,7 @@ class BaseIcon extends St.Bin {
function clamp(value, min, max) {
return Math.max(Math.min(value, max), min);
};
}
function zoomOutActor(actor) {
let actorClone = new Clutter.Clone({ source: actor,
@ -179,8 +179,8 @@ function zoomOutActor(actor) {
}
var IconGrid = GObject.registerClass({
Signals: {'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype]} },
Signals: { 'animation-done': {},
'child-focused': { param_types: [Clutter.Actor.$gtype] } },
}, class IconGrid extends St.Widget {
_init(params) {
super._init({ style_class: 'icon-grid',
@ -276,7 +276,7 @@ var IconGrid = GObject.registerClass({
if (forWidth < 0)
nColumns = children.length;
else
[nColumns, ] = this._computeLayout(forWidth);
[nColumns] = this._computeLayout(forWidth);
let nRows;
if (nColumns > 0)
@ -311,17 +311,18 @@ var IconGrid = GObject.registerClass({
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch(this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let animating = this._clonesAnimating.length > 0;
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
@ -331,10 +332,11 @@ var IconGrid = GObject.registerClass({
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
children[i].hide();
children[i].opacity = 0;
} else {
if (!animating)
children[i].opacity = 255;
children[i].allocate(childBox, flags);
children[i].show();
}
columnIndex++;
@ -375,15 +377,15 @@ var IconGrid = GObject.registerClass({
return true;
for (let child = this.get_first_child();
child != null;
child = child.get_next_sibling()) {
child != null;
child = child.get_next_sibling()) {
if (!child.visible)
if (!child.visible || !child.opacity)
continue;
let childVolume = child.get_transformed_paint_volume(this);
if (!childVolume)
return false
return false;
paintVolume.union(childVolume);
}
@ -400,7 +402,7 @@ var IconGrid = GObject.registerClass({
}
_cancelAnimation() {
this._clonesAnimating.forEach(clone => { clone.destroy(); });
this._clonesAnimating.forEach(clone => clone.destroy());
this._clonesAnimating = [];
}
@ -443,24 +445,24 @@ var IconGrid = GObject.registerClass({
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();
}
});
}
});
{ 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();
}
});
}
});
}
}
@ -502,7 +504,7 @@ var IconGrid = GObject.registerClass({
this._clonesAnimating.push(actorClone);
Main.uiGroup.add_actor(actorClone);
let [width, height,,] = this._getAllocatedChildSizeAndSpacing(actor);
let [width, height] = this._getAllocatedChildSizeAndSpacing(actor);
actorClone.set_size(width, height);
let scaleX = sourceScaledWidth / width;
let scaleY = sourceScaledHeight / height;
@ -529,7 +531,7 @@ var IconGrid = GObject.registerClass({
onComplete: () => {
if (isLastItem)
this._animationDone();
}};
} };
fadeParams = { time: ANIMATION_FADE_IN_TIME_FOR_ITEM,
transition: 'easeInOutQuad',
delay: delay,
@ -551,7 +553,7 @@ var IconGrid = GObject.registerClass({
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,
@ -600,6 +602,8 @@ var IconGrid = GObject.registerClass({
}
_computeLayout(forWidth) {
this.ensure_style();
let nColumns = 0;
let usedWidth = this.leftPadding + this.rightPadding;
let spacing = this._getSpacing();
@ -708,8 +712,8 @@ var IconGrid = GObject.registerClass({
if (this._padWithSpacing) {
// minRows + 1 because we want to put spacing before the first row, so it is like we have one more row
// to divide the empty space
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows +1));
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns +1));
maxVSpacing = Math.floor(maxEmptyVArea / (this._minRows + 1));
maxHSpacing = Math.floor(maxEmptyHArea / (this._minColumns + 1));
} else {
if (this._minRows <= 1)
maxVSpacing = maxEmptyVArea;
@ -741,11 +745,10 @@ var IconGrid = GObject.registerClass({
this._fixedHItemSize = this._hItemSize;
this._fixedVItemSize = this._vItemSize;
this._updateSpacingForSize(availWidth, availHeight);
let spacing = this._getSpacing();
if (this.columnsForWidth(availWidth) < this._minColumns || this.rowsForHeight(availHeight) < this._minRows) {
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth ;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight ;
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
@ -769,8 +772,8 @@ var IconGrid = GObject.registerClass({
});
var PaginatedIconGrid = GObject.registerClass({
Signals: {'space-opened': {},
'space-closed': {} },
Signals: { 'space-opened': {},
'space-closed': {} },
}, class PaginatedIconGrid extends IconGrid {
_init(params) {
super._init(params);
@ -787,7 +790,7 @@ var PaginatedIconGrid = GObject.registerClass({
}
vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
this.set_allocation(box, flags);
@ -800,26 +803,24 @@ var PaginatedIconGrid = GObject.registerClass({
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let spacing = this._getSpacing();
let [nColumns, usedWidth] = this._computeLayout(availWidth);
let leftEmptySpace;
switch(this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((availWidth - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
@ -829,15 +830,15 @@ var PaginatedIconGrid = GObject.registerClass({
columnIndex++;
if (columnIndex == nColumns) {
columnIndex = 0;
rowIndex++;
}
if (columnIndex == 0) {
y += this._getVItemSize() + spacing;
if ((i + 1) % this._childrenPerPage == 0)
y += this._spaceBetweenPages - spacing + this.bottomPadding + this.topPadding;
x = box.x1 + leftEmptySpace + this.leftPadding;
} else
} else {
x += this._getHItemSize() + spacing;
}
}
}
@ -861,7 +862,6 @@ var PaginatedIconGrid = GObject.registerClass({
if (this._rowLimit)
nRows = Math.min(nRows, this._rowLimit);
let spacing = this._getSpacing();
// We want to contain the grid inside the parent box with padding
this._rowsPerPage = this.rowsForHeight(availHeightPerPage);
this._nPages = Math.ceil(nRows / this._rowsPerPage);
@ -890,7 +890,7 @@ var PaginatedIconGrid = GObject.registerClass({
if (!this._nPages)
return 0;
let firstPageItem = pageNumber * this._childrenPerPage
let firstPageItem = pageNumber * this._childrenPerPage;
let childBox = this._getVisibleChildren()[firstPageItem].get_allocation_box();
return childBox.y1 - this.topPadding;
}
@ -969,7 +969,7 @@ var PaginatedIconGrid = GObject.registerClass({
transition: 'easeInOutQuad'
};
if (i == (children.length - 1))
params.onComplete = () => { this.emit('space-opened'); };
params.onComplete = () => this.emit('space-opened');
Tweener.addTween(children[i], params);
}
}
@ -987,7 +987,7 @@ var PaginatedIconGrid = GObject.registerClass({
{ translation_y: 0,
time: EXTRA_SPACE_ANIMATION_TIME,
transition: 'easeInOutQuad',
onComplete: () => { this.emit('space-closed'); }
onComplete: () => this.emit('space-closed')
});
}
}

View File

@ -111,7 +111,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
}
vfunc_show() {
if (this._app && APP_WHITELIST.indexOf(this._app.get_id()) != -1) {
if (this._app && APP_WHITELIST.includes(this._app.get_id())) {
this._emitResponse(DialogResponse.ALLOW);
return;
}

View File

@ -24,29 +24,29 @@ const SHOW_KEYBOARD = 'screen-keyboard-enabled';
const KEY_SIZE = 2;
const defaultKeysPre = [
[ [], [], [{ width: 1.5, level: 1, extraClassName: 'shift-key-lowercase' }], [{ label: '?123', width: 1.5, level: 2 }] ],
[ [], [], [{ width: 1.5, level: 0, extraClassName: 'shift-key-uppercase' }], [{ label: '?123', width: 1.5, level: 2 }] ],
[ [], [], [{ label: '=/<', width: 1.5, level: 3 }], [{ label: 'ABC', width: 1.5, level: 0 }] ],
[ [], [], [{ label: '?123', width: 1.5, level: 2 }], [{ label: 'ABC', width: 1.5, level: 0 }] ],
[[], [], [{ width: 1.5, level: 1, extraClassName: 'shift-key-lowercase' }], [{ label: '?123', width: 1.5, level: 2 }]],
[[], [], [{ width: 1.5, level: 0, extraClassName: 'shift-key-uppercase' }], [{ label: '?123', width: 1.5, level: 2 }]],
[[], [], [{ label: '=/<', width: 1.5, level: 3 }], [{ label: 'ABC', width: 1.5, level: 0 }]],
[[], [], [{ label: '?123', width: 1.5, level: 2 }], [{ label: 'ABC', width: 1.5, level: 0 }]],
];
const defaultKeysPost = [
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '=/<', width: 3, level: 3, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[ [{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '?123', width: 3, level: 2, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }] ],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 1, right: true, extraClassName: 'shift-key-lowercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ width: 3, level: 0, right: true, extraClassName: 'shift-key-uppercase' }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '=/<', width: 3, level: 3, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
[[{ label: '⌫', width: 1.5, keyval: Clutter.KEY_BackSpace }],
[{ width: 2, keyval: Clutter.KEY_Return, extraClassName: 'enter-key' }],
[{ label: '?123', width: 3, level: 2, right: true }],
[{ label: '☻', action: 'emoji' }, { action: 'languageMenu', extraClassName: 'layout-key' }, { action: 'hide', extraClassName: 'hide-key' }]],
];
var AspectContainer = GObject.registerClass(
@ -282,7 +282,7 @@ var Key = class Key {
y_fill: true,
x_align: St.Align.START });
this._boxPointer.hide();
Main.layoutManager.addChrome(this._boxPointer);
Main.layoutManager.addTopChrome(this._boxPointer);
this._boxPointer.setPosition(this.keyButton, 0.5);
// Adds style to existing keyboard style to avoid repetition
@ -297,7 +297,7 @@ var Key = class Key {
}
_press(key) {
this.emit('activated')
this.emit('activated');
if (key != this.key || this._extended_keys.length == 0) {
this.emit('pressed', this._getKeyval(key), key);
@ -405,9 +405,6 @@ var Key = class Key {
return Clutter.EVENT_PROPAGATE;
});
button.connect('touch-event', (actor, event) => {
let device = event.get_device();
let sequence = event.get_event_sequence();
// We only handle touch events here on wayland. On X11
// we do get emulated pointer events, which already works
// for single-touch cases. Besides, the X11 passive touch grab
@ -683,7 +680,7 @@ var EmojiPager = class EmojiPager {
_onPanEnd() {
if (Math.abs(this._delta) < this.actor.width * PANEL_SWITCH_RELATIVE_DISTANCE) {
this._onPanCancel()
this._onPanCancel();
} else {
let value;
if (this._delta > 0)
@ -865,7 +862,7 @@ var EmojiSelection = class EmojiSelection {
x_expand: true,
y_expand: true,
vertical: true });
this.actor.connect('notify::mapped', () => { this._emojiPager.setCurrentPage(0); });
this.actor.connect('notify::mapped', () => this._emojiPager.setCurrentPage(0));
this._emojiPager = new EmojiPager(this._sections, 11, 3);
this._emojiPager.connect('page-changed', (pager, section, page, nPages) => {
@ -913,7 +910,6 @@ var EmojiSelection = class EmojiSelection {
contents = imports.byteArray.toString(contents);
let emoji = JSON.parse(contents);
let pages = [];
let variants = [];
let currentKey = 0;
let currentSection = null;
@ -948,14 +944,14 @@ var EmojiSelection = class EmojiSelection {
key = new Key('ABC', []);
key.keyButton.add_style_class_name('default-key');
key.connect('released', () => { this.emit('toggle'); });
key.connect('released', () => this.emit('toggle'));
row.appendKey(key.actor, 1.5);
for (let i = 0; i < this._sections.length; i++) {
let section = this._sections[i];
key = new Key(section.label, []);
key.connect('released', () => { this._emojiPager.setCurrentSection(section, 0) });
key.connect('released', () => this._emojiPager.setCurrentSection(section, 0));
row.appendKey(key.actor);
section.button = key;
@ -1074,7 +1070,7 @@ var Keyboard = class Keyboard {
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId);
if (device.get_device_name().indexOf('XTEST') < 0) {
if (!device.get_device_name().includes('XTEST')) {
this._lastDeviceId = deviceId;
this._syncEnabled();
}
@ -1175,7 +1171,7 @@ var Keyboard = class Keyboard {
this._emojiSelection = new EmojiSelection();
this._emojiSelection.connect('toggle', this._toggleEmoji.bind(this));
this._emojiSelection.connect('hide', (selection) => { this.hide(); });
this._emojiSelection.connect('hide', (selection) => this.hide());
this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
this._keyboardController.commitString(emoji);
});
@ -1228,12 +1224,12 @@ var Keyboard = class Keyboard {
}
if (!this._showIdleId) {
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex);
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
this._showIdleId = GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => {
this.show(Main.layoutManager.focusIndex);
this._showIdleId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._showIdleId, '[gnome-shell] this.show');
}
}
@ -1306,7 +1302,7 @@ var Keyboard = class Keyboard {
this._languagePopup.destroy();
this._languagePopup = new LanguageSelectionPopup(keyActor);
Main.layoutManager.addChrome(this._languagePopup.actor);
Main.layoutManager.addTopChrome(this._languagePopup.actor);
this._languagePopup.open(true);
}
@ -1406,8 +1402,6 @@ var Keyboard = class Keyboard {
}
_getDefaultKeysForRow(row, numRows, level) {
let pre, post;
/* The first 2 rows in defaultKeysPre/Post belong together with
* the first 2 rows on each keymap. On keymaps that have more than
* 4 rows, the last 2 default key rows must be respectively
@ -1448,8 +1442,8 @@ var Keyboard = class Keyboard {
numOfVertSlots = rows.length;
for (let i = 0; i < rows.length; ++i) {
let keyboard_row = rows[i];
let keys = keyboard_row.get_children();
let keyboardRow = rows[i];
let keys = keyboardRow.get_children();
numOfHorizSlots = Math.max(numOfHorizSlots, keys.length);
}
@ -1646,8 +1640,7 @@ var Keyboard = class Keyboard {
}
_windowSlideAnimationComplete(window, delta) {
// Synchronize window and actor positions again.
let windowActor = window.get_compositor_private();
// Synchronize window positions again.
let frameRect = window.get_frame_rect();
frameRect.y += delta;
window.move_frame(true, frameRect.x, frameRect.y);
@ -1688,12 +1681,11 @@ var Keyboard = class Keyboard {
this._animFocusedWindow = window;
}
setCursorLocation(window, x, y , w, h) {
setCursorLocation(window, x, y, w, h) {
let monitor = Main.layoutManager.keyboardMonitor;
if (window && monitor) {
let keyboardHeight = Main.layoutManager.keyboardBox.height;
let focusObscured = false;
if (y + h >= monitor.y + monitor.height - keyboardHeight) {
if (this._keyboardVisible)
@ -1744,7 +1736,6 @@ var KeyboardController = class {
}
_onContentPurposeHintsChanged(method) {
let hints = method.content_hints;
let purpose = method.content_purpose;
let emojiVisible = false;
let keypadVisible = false;
@ -1759,13 +1750,13 @@ var KeyboardController = class {
purpose == Clutter.InputContentPurpose.PHONE)
keypadVisible = true;
this.emit('emoji-visible', emojiVisible)
this.emit('emoji-visible', emojiVisible);
this.emit('keypad-visible', keypadVisible);
}
getGroups() {
let inputSources = this._inputSourceManager.inputSources;
let groups = []
let groups = [];
for (let i in inputSources) {
let is = inputSources[i];

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Background = imports.ui.background;
@ -11,6 +11,7 @@ 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;
@ -20,7 +21,7 @@ var HOT_CORNER_PRESSURE_THRESHOLD = 100; // pixels
var HOT_CORNER_PRESSURE_TIMEOUT = 1000; // ms
function isPopupMetaWindow(actor) {
switch(actor.meta_window.get_window_type()) {
switch (actor.meta_window.get_window_type()) {
case Meta.WindowType.DROPDOWN_MENU:
case Meta.WindowType.POPUP_MENU:
case Meta.WindowType.COMBO:
@ -31,18 +32,20 @@ function isPopupMetaWindow(actor) {
}
var MonitorConstraint = GObject.registerClass({
Properties: {'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1),
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)},
Properties: {
'primary': GObject.ParamSpec.boolean('primary',
'Primary', 'Track primary monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false),
'index': GObject.ParamSpec.int('index',
'Monitor index', 'Track specific monitor',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
-1, 64, -1),
'work-area': GObject.ParamSpec.boolean('work-area',
'Work-area', 'Track monitor\'s work-area',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
false)
},
}, class MonitorConstraint extends Clutter.Constraint {
_init(props) {
this._primary = false;
@ -146,13 +149,13 @@ var MonitorConstraint = GObject.registerClass({
});
var Monitor = class Monitor {
constructor(index, geometry, geometry_scale) {
constructor(index, geometry, geometryScale) {
this.index = index;
this.x = geometry.x;
this.y = geometry.y;
this.width = geometry.width;
this.height = geometry.height;
this.geometry_scale = geometry_scale;
this.geometry_scale = geometryScale;
}
get inFullscreen() {
@ -238,7 +241,7 @@ var LayoutManager = GObject.registerClass({
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.addTopChrome(this.screenShieldGroup);
this.addChrome(this.screenShieldGroup);
this.panelBox = new St.BoxLayout({ name: 'panelBox',
vertical: true });
@ -271,6 +274,13 @@ var LayoutManager = GObject.registerClass({
this._backgroundGroup.lower_bottom();
this._bgManagers = [];
this._interfaceSettings = new Gio.Settings({
schema_id: 'org.gnome.desktop.interface'
});
this._interfaceSettings.connect('changed::enable-hot-corners',
this._updateHotCorners.bind(this));
// Need to update struts on new workspaces when they are added
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
@ -374,6 +384,11 @@ var LayoutManager = GObject.registerClass({
});
this.hotCorners = [];
if (!this._interfaceSettings.get_boolean('enable-hot-corners')) {
this.emit('hot-corners-changed');
return;
}
let size = this.panelBox.height;
// build new hot corners
@ -826,7 +841,7 @@ var LayoutManager = GObject.registerClass({
// @params can have any of the same values as in addChrome(),
// though some possibilities don't make sense. By default, @actor has
// the same params as its chrome ancestor.
trackChrome(actor, params) {
trackChrome(actor, params = {}) {
let ancestor = actor.get_parent();
let index = this._findActor(ancestor);
while (ancestor && index == -1) {
@ -836,8 +851,6 @@ var LayoutManager = GObject.registerClass({
let ancestorData = ancestor ? this._trackedActors[index]
: defaultParams;
if (!params)
params = {};
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
@ -1066,14 +1079,13 @@ var LayoutManager = GObject.registerClass({
else
continue;
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1});
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 });
let strut = new Meta.Strut({ rect: strutRect, side: side });
struts.push(strut);
}
}
if (!Meta.is_wayland_compositor())
global.set_stage_input_region(rects);
global.set_stage_input_region(rects);
this._isPopupWindowVisible = isPopupMenuVisible;
let workspaceManager = global.workspace_manager;
@ -1118,14 +1130,15 @@ var HotCorner = class HotCorner {
Shell.ActionMode.OVERVIEW);
this._pressureBarrier.connect('trigger', this._toggleOverview.bind(this));
// Cache the three ripples instead of dynamically creating and destroying them.
this._ripple1 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple2 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
this._ripple3 = new St.BoxLayout({ style_class: 'ripple-box', opacity: 0, visible: false });
let px = 0.0;
let py = 0.0;
if (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL) {
px = 1.0;
py = 0.0;
}
layoutManager.uiGroup.add_actor(this._ripple1);
layoutManager.uiGroup.add_actor(this._ripple2);
layoutManager.uiGroup.add_actor(this._ripple3);
this._ripples = new Ripples.Ripples(px, py, 'ripple-box');
this._ripples.addTo(layoutManager.uiGroup);
}
setBarrierSize(size) {
@ -1207,53 +1220,12 @@ var HotCorner = class HotCorner {
this.actor.destroy();
}
_animRipple(ripple, delay, time, 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
// it more visible in the middle section.
ripple._opacity = startOpacity;
if (ripple.get_text_direction() == Clutter.TextDirection.RTL)
ripple.set_anchor_point_from_gravity(Clutter.Gravity.NORTH_EAST);
ripple.visible = true;
ripple.opacity = 255 * Math.sqrt(startOpacity);
ripple.scale_x = ripple.scale_y = startScale;
ripple.x = this._x;
ripple.y = this._y;
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; } });
}
_rippleAnimation() {
// Show three concentric ripples expanding outwards; the exact
// 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);
}
_toggleOverview() {
if (this._monitor.inFullscreen && !Main.overview.visible)
return;
if (Main.overview.shouldToggleByCornerOrButton()) {
this._rippleAnimation();
this._ripples.playAnimation(this._x, this._y);
Main.overview.toggle();
}
}

View File

@ -7,7 +7,7 @@ const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
var DEFAULT_FADE_FACTOR = 0.4;
var VIGNETTE_BRIGHTNESS = 0.8;
var VIGNETTE_BRIGHTNESS = 0.2;
var VIGNETTE_SHARPNESS = 0.7;
const VIGNETTE_DECLARATIONS = '\

24
js/ui/locatePointer.js Normal file
View File

@ -0,0 +1,24 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Gio } = imports.gi;
const Ripples = imports.ui.ripples;
const Main = imports.ui.main;
const LOCATE_POINTER_KEY = "locate-pointer";
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);
}
show() {
if (!this._settings.get_boolean(LOCATE_POINTER_KEY))
return;
let [x, y, mods] = global.get_pointer();
this._ripples.playAnimation(x, y);
}
};

View File

@ -7,13 +7,14 @@ const Signals = imports.signals;
const System = imports.system;
const History = imports.misc.history;
const ExtensionSystem = imports.ui.extensionSystem;
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;
const { ExtensionState } = ExtensionUtils;
const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
@ -68,10 +69,10 @@ var AutoComplete = class AutoComplete {
if (commonPrefix.length > 0) {
this.additionalCompletionText(commonPrefix, event.attrHead);
this.emit('completion', { completion: commonPrefix, type: 'prefix' });
this.emit('suggest', { completions: event.completions});
this.emit('suggest', { completions: event.completions });
}
} else if (event.completions.length > 1 && event.tabType === 'double') {
this.emit('suggest', { completions: event.completions});
this.emit('suggest', { completions: event.completions });
}
}
@ -146,8 +147,8 @@ var Notebook = class Notebook {
this.actor.add(scrollview, { expand: true });
let vAdjust = scrollview.vscroll.adjustment;
vAdjust.connect('changed', () => { this._onAdjustScopeChanged(tabData); });
vAdjust.connect('notify::value', () => { this._onAdjustValueChanged(tabData); });
vAdjust.connect('changed', () => this._onAdjustScopeChanged(tabData));
vAdjust.connect('notify::value', () => this._onAdjustValueChanged(tabData));
if (this._selectedIndex == -1)
this.selectIndex(0);
@ -185,9 +186,9 @@ var Notebook = class Notebook {
}
selectChild(child) {
if (child == null)
if (child == null) {
this.selectIndex(-1);
else {
} else {
for (let i = 0; i < this._tabs.length; i++) {
let tabData = this._tabs[i];
if (tabData.child == child) {
@ -242,7 +243,7 @@ function objectToString(o) {
// special case this since the default is way, way too verbose
return '<js function>';
} else {
return '' + o;
return `${o}`;
}
}
@ -284,7 +285,7 @@ var Result = class Result {
this.actor.add(cmdTxt);
let box = new St.BoxLayout({});
this.actor.add(box);
let resultTxt = new St.Label({ text: 'r(' + index + ') = ' });
let resultTxt = new St.Label({ text: `r(${index}) = ` });
resultTxt.clutter_text.ellipsize = Pango.EllipsizeMode.END;
box.add(resultTxt);
let objLink = new ObjLink(this._lookingGlass, o);
@ -320,7 +321,7 @@ var WindowList = class WindowList {
box.add(windowLink.actor, { x_align: St.Align.START, x_fill: false });
let propsBox = new St.BoxLayout({ vertical: true, style: 'padding-left: 6px;' });
box.add(propsBox);
propsBox.add(new St.Label({ text: 'wmclass: ' + metaWindow.get_wm_class() }));
propsBox.add(new St.Label({ text: `wmclass: ${metaWindow.get_wm_class()}` }));
let app = tracker.get_window_app(metaWindow);
if (app != null && !app.is_window_backed()) {
let icon = app.create_icon_texture(22);
@ -394,7 +395,6 @@ var ObjInspector = class ObjInspector {
for (let i = 0; i < properties.length; i++) {
let propName = properties[i];
let valueStr;
let link;
try {
let prop = obj[propName];
@ -403,8 +403,7 @@ var ObjInspector = class ObjInspector {
link = new St.Label({ text: '<error>' });
}
let hbox = new St.BoxLayout();
let propText = propName + ': ' + valueStr;
hbox.add(new St.Label({ text: propName + ': ' }));
hbox.add(new St.Label({ text: `${propName}: ` }));
hbox.add(link);
this._container.add_actor(hbox);
}
@ -493,8 +492,13 @@ var Inspector = GObject.registerClass({
eventHandler.connect('button-press-event', this._onButtonPressEvent.bind(this));
eventHandler.connect('scroll-event', this._onScrollEvent.bind(this));
eventHandler.connect('motion-event', this._onMotionEvent.bind(this));
Clutter.grab_pointer(eventHandler);
Clutter.grab_keyboard(eventHandler);
let dm = Clutter.DeviceManager.get_default();
this._pointerDevice = dm.get_core_device(Clutter.InputDeviceType.POINTER_DEVICE);
this._keyboardDevice = dm.get_core_device(Clutter.InputDeviceType.KEYBOARD_DEVICE);
this._pointerDevice.grab(eventHandler);
this._keyboardDevice.grab(eventHandler);
// this._target is the actor currently shown by the inspector.
// this._pointerTarget is the actor directly under the pointer.
@ -527,8 +531,8 @@ var Inspector = GObject.registerClass({
}
_close() {
Clutter.ungrab_pointer();
Clutter.ungrab_keyboard();
this._pointerDevice.ungrab();
this._keyboardDevice.ungrab();
this._eventHandler.destroy();
this._eventHandler = null;
this.emit('closed');
@ -551,7 +555,7 @@ var Inspector = GObject.registerClass({
_onScrollEvent(actor, event) {
switch (event.get_scroll_direction()) {
case Clutter.ScrollDirection.UP:
case Clutter.ScrollDirection.UP: {
// select parent
let parent = this._target.get_parent();
if (parent != null) {
@ -559,6 +563,7 @@ var Inspector = GObject.registerClass({
this._update(event);
}
break;
}
case Clutter.ScrollDirection.DOWN:
// select child
@ -598,9 +603,9 @@ var Inspector = GObject.registerClass({
this._target = target;
this._pointerTarget = target;
let position = '[inspect x: ' + stageX + ' y: ' + stageY + ']';
let position = `[inspect x: ${stageX} y: ${stageY}]`;
this._displayText.text = '';
this._displayText.text = position + ' ' + this._target;
this._displayText.text = `${position} ${this._target}`;
this._lookingGlass.setBorderPaintTarget(this._target);
}
@ -612,22 +617,23 @@ var Extensions = class Extensions {
this.actor = new St.BoxLayout({ vertical: true,
name: 'lookingGlassExtensions' });
this._noExtensions = new St.Label({ style_class: 'lg-extensions-none',
text: _("No extensions installed") });
text: _("No extensions installed") });
this._numExtensions = 0;
this._extensionsList = new St.BoxLayout({ vertical: true,
style_class: 'lg-extensions-list' });
this._extensionsList.add(this._noExtensions);
this.actor.add(this._extensionsList);
for (let uuid in ExtensionUtils.extensions)
Main.extensionManager.getUuids().forEach(uuid => {
this._loadExtension(null, uuid);
});
ExtensionSystem.connect('extension-loaded',
this._loadExtension.bind(this));
Main.extensionManager.connect('extension-loaded',
this._loadExtension.bind(this));
}
_loadExtension(o, uuid) {
let extension = ExtensionUtils.extensions[uuid];
let extension = Main.extensionManager.lookup(uuid);
// There can be cases where we create dummy extension metadata
// that's not really a proper extension. Don't bother with these.
if (!extension.metadata.name)
@ -684,17 +690,17 @@ var Extensions = class Extensions {
_stateToString(extensionState) {
switch (extensionState) {
case ExtensionSystem.ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionSystem.ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
return _("Error");
case ExtensionSystem.ExtensionState.OUT_OF_DATE:
return _("Out of date");
case ExtensionSystem.ExtensionState.DOWNLOADING:
return _("Downloading");
case ExtensionState.ENABLED:
return _("Enabled");
case ExtensionState.DISABLED:
case ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionState.ERROR:
return _("Error");
case ExtensionState.OUT_OF_DATE:
return _("Out of date");
case ExtensionState.DOWNLOADING:
return _("Downloading");
}
return 'Unknown'; // Not translated, shouldn't appear
}
@ -702,7 +708,7 @@ var Extensions = class Extensions {
_createExtensionDisplay(extension) {
let box = new St.BoxLayout({ style_class: 'lg-extension', vertical: true });
let name = new St.Label({ style_class: 'lg-extension-name',
text: extension.metadata.name });
text: extension.metadata.name });
box.add(name, { expand: true });
let description = new St.Label({ style_class: 'lg-extension-description',
text: extension.metadata.description || 'No description' });
@ -710,7 +716,6 @@ var Extensions = class Extensions {
let metaBox = new St.BoxLayout({ style_class: 'lg-extension-meta' });
box.add(metaBox);
let stateString = this._stateToString(extension.state);
let state = new St.Label({ style_class: 'lg-extension-state',
text: this._stateToString(extension.state) });
metaBox.add(state);
@ -795,7 +800,7 @@ var LookingGlass = class LookingGlass {
inspectIcon.connect('button-press-event', () => {
let inspector = new Inspector(this);
inspector.connect('target', (i, target, stageX, stageY) => {
this._pushResult('inspect(' + Math.round(stageX) + ', ' + Math.round(stageY) + ')', target);
this._pushResult(`inspect(${Math.round(stageX)}, ${Math.round(stageY)})`, target);
});
inspector.connect('closed', () => {
this.actor.show();
@ -810,15 +815,15 @@ var LookingGlass = class LookingGlass {
toolbar.add_actor(gcIcon);
gcIcon.reactive = true;
gcIcon.connect('button-press-event', () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
gcIcon.icon_name = 'user-trash-full';
this._timeoutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'user-trash-full\'');
return Clutter.EVENT_PROPAGATE;
});
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] gcIcon.icon_name = \'user-trash-full\'');
return Clutter.EVENT_PROPAGATE;
});
let notebook = new Notebook();
@ -889,9 +894,11 @@ var LookingGlass = class LookingGlass {
let fontDesc = Pango.FontDescription.from_string(fontName);
// We ignore everything but size and style; you'd be crazy to set your system-wide
// monospace font to be bold/oblique/etc. Could easily be added here.
this.actor.style =
'font-size: ' + fontDesc.get_size() / 1024. + (fontDesc.get_size_is_absolute() ? 'px' : 'pt') + ';'
+ 'font-family: "' + fontDesc.get_family() + '";';
let size = fontDesc.get_size() / 1024.;
let unit = fontDesc.get_size_is_absolute() ? 'px' : 'pt';
this.actor.style = `
font-size: ${size}${unit};
font-family: "${fontDesc.get_family()}";`;
}
setBorderPaintTarget(obj) {
@ -977,7 +984,7 @@ var LookingGlass = class LookingGlass {
try {
resultObj = Function(fullCmd)();
} catch (e) {
resultObj = '<exception ' + e + '>';
resultObj = `<exception ${e}>`;
}
this._pushResult(command, resultObj);
@ -1004,7 +1011,7 @@ var LookingGlass = class LookingGlass {
}
_queueResize() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => { this._resize(); });
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => this._resize());
}
_resize() {

View File

@ -41,10 +41,8 @@ const CROSS_HAIRS_OPACITY_KEY = 'cross-hairs-opacity';
const CROSS_HAIRS_LENGTH_KEY = 'cross-hairs-length';
const CROSS_HAIRS_CLIP_KEY = 'cross-hairs-clip';
let magDBusService = null;
var MouseSpriteContent = GObject.registerClass({
Implements: [ Clutter.Content ],
Implements: [Clutter.Content],
}, class MouseSpriteContent extends GObject.Object {
_init() {
super._init();
@ -122,7 +120,7 @@ var Magnifier = class Magnifier {
});
// Export to dbus.
magDBusService = new MagnifierDBus.ShellMagnifier();
(new MagnifierDBus.ShellMagnifier());
this.setActive(St.Settings.get().magnifier_active);
}
@ -150,7 +148,7 @@ var Magnifier = class Magnifier {
setActive(activate) {
let isActive = this.isActive();
this._zoomRegions.forEach ((zoomRegion, index, array) => {
this._zoomRegions.forEach((zoomRegion, index, array) => {
zoomRegion.setActive(activate);
});
@ -284,7 +282,7 @@ var Magnifier = class Magnifier {
* @zoomRegion: The zoomRegion to add.
*/
addZoomRegion(zoomRegion) {
if(zoomRegion) {
if (zoomRegion) {
this._zoomRegions.push(zoomRegion);
if (!this.isTrackingMouse())
this.startTrackingMouse();
@ -349,8 +347,7 @@ var Magnifier = class Magnifier {
if (!this._crossHairs)
this.addCrosshairs();
this._crossHairs.show();
}
else {
} else {
if (this._crossHairs)
this._crossHairs.hide();
}
@ -377,9 +374,9 @@ var Magnifier = class Magnifier {
if (this._crossHairs) {
let clutterColor = this._crossHairs.getColor();
return clutterColor.to_string();
}
else
} else {
return '#00000000';
}
}
/**
@ -459,8 +456,7 @@ var Magnifier = class Magnifier {
if (clip) {
if (this._crossHairs)
this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE);
}
else {
} else {
// Setting no clipping on crosshairs means a zero sized clip
// rectangle.
if (this._crossHairs)
@ -473,14 +469,14 @@ var Magnifier = class Magnifier {
* Get whether the crosshairs are clipped by the mouse image.
* @return: Whether the crosshairs are clipped.
*/
getCrosshairsClip() {
getCrosshairsClip() {
if (this._crossHairs) {
let [clipWidth, clipHeight] = this._crossHairs.getClip();
return (clipWidth > 0 && clipHeight > 0);
}
else
} else {
return false;
}
}
}
//// Private methods ////
@ -504,61 +500,61 @@ var Magnifier = class Magnifier {
_settingsInit(zoomRegion) {
this._settings = new Gio.Settings({ schema_id: MAGNIFIER_SCHEMA });
this._settings.connect('changed::' + SCREEN_POSITION_KEY,
this._settings.connect(`changed::${SCREEN_POSITION_KEY}`,
this._updateScreenPosition.bind(this));
this._settings.connect('changed::' + MAG_FACTOR_KEY,
this._settings.connect(`changed::${MAG_FACTOR_KEY}`,
this._updateMagFactor.bind(this));
this._settings.connect('changed::' + LENS_MODE_KEY,
this._settings.connect(`changed::${LENS_MODE_KEY}`,
this._updateLensMode.bind(this));
this._settings.connect('changed::' + CLAMP_MODE_KEY,
this._settings.connect(`changed::${CLAMP_MODE_KEY}`,
this._updateClampMode.bind(this));
this._settings.connect('changed::' + MOUSE_TRACKING_KEY,
this._settings.connect(`changed::${MOUSE_TRACKING_KEY}`,
this._updateMouseTrackingMode.bind(this));
this._settings.connect('changed::' + FOCUS_TRACKING_KEY,
this._settings.connect(`changed::${FOCUS_TRACKING_KEY}`,
this._updateFocusTrackingMode.bind(this));
this._settings.connect('changed::' + CARET_TRACKING_KEY,
this._settings.connect(`changed::${CARET_TRACKING_KEY}`,
this._updateCaretTrackingMode.bind(this));
this._settings.connect('changed::' + INVERT_LIGHTNESS_KEY,
this._settings.connect(`changed::${INVERT_LIGHTNESS_KEY}`,
this._updateInvertLightness.bind(this));
this._settings.connect('changed::' + COLOR_SATURATION_KEY,
this._settings.connect(`changed::${COLOR_SATURATION_KEY}`,
this._updateColorSaturation.bind(this));
this._settings.connect('changed::' + BRIGHT_RED_KEY,
this._settings.connect(`changed::${BRIGHT_RED_KEY}`,
this._updateBrightness.bind(this));
this._settings.connect('changed::' + BRIGHT_GREEN_KEY,
this._settings.connect(`changed::${BRIGHT_GREEN_KEY}`,
this._updateBrightness.bind(this));
this._settings.connect('changed::' + BRIGHT_BLUE_KEY,
this._settings.connect(`changed::${BRIGHT_BLUE_KEY}`,
this._updateBrightness.bind(this));
this._settings.connect('changed::' + CONTRAST_RED_KEY,
this._settings.connect(`changed::${CONTRAST_RED_KEY}`,
this._updateContrast.bind(this));
this._settings.connect('changed::' + CONTRAST_GREEN_KEY,
this._settings.connect(`changed::${CONTRAST_GREEN_KEY}`,
this._updateContrast.bind(this));
this._settings.connect('changed::' + CONTRAST_BLUE_KEY,
this._settings.connect(`changed::${CONTRAST_BLUE_KEY}`,
this._updateContrast.bind(this));
this._settings.connect('changed::' + SHOW_CROSS_HAIRS_KEY, () => {
this._settings.connect(`changed::${SHOW_CROSS_HAIRS_KEY}`, () => {
this.setCrosshairsVisible(this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY));
});
this._settings.connect('changed::' + CROSS_HAIRS_THICKNESS_KEY, () => {
this._settings.connect(`changed::${CROSS_HAIRS_THICKNESS_KEY}`, () => {
this.setCrosshairsThickness(this._settings.get_int(CROSS_HAIRS_THICKNESS_KEY));
});
this._settings.connect('changed::' + CROSS_HAIRS_COLOR_KEY, () => {
this._settings.connect(`changed::${CROSS_HAIRS_COLOR_KEY}`, () => {
this.setCrosshairsColor(this._settings.get_string(CROSS_HAIRS_COLOR_KEY));
});
this._settings.connect('changed::' + CROSS_HAIRS_OPACITY_KEY, () => {
this._settings.connect(`changed::${CROSS_HAIRS_OPACITY_KEY}`, () => {
this.setCrosshairsOpacity(this._settings.get_double(CROSS_HAIRS_OPACITY_KEY));
});
this._settings.connect('changed::' + CROSS_HAIRS_LENGTH_KEY, () => {
this._settings.connect(`changed::${CROSS_HAIRS_LENGTH_KEY}`, () => {
this.setCrosshairsLength(this._settings.get_int(CROSS_HAIRS_LENGTH_KEY));
});
this._settings.connect('changed::' + CROSS_HAIRS_CLIP_KEY, () => {
this._settings.connect(`changed::${CROSS_HAIRS_CLIP_KEY}`, () => {
this.setCrosshairsClip(this._settings.get_boolean(CROSS_HAIRS_CLIP_KEY));
});
@ -610,7 +606,7 @@ var Magnifier = class Magnifier {
let showCrosshairs = this._settings.get_boolean(SHOW_CROSS_HAIRS_KEY);
this.addCrosshairs();
this.setCrosshairsVisible(showCrosshairs);
}
}
_updateScreenPosition() {
// Applies only to the first zoom region.
@ -800,8 +796,8 @@ var ZoomRegion = class ZoomRegion {
let extents;
try {
extents = component.get_extents(Atspi.CoordType.SCREEN);
} catch(e) {
log('Failed to read extents of focused component: ' + e.message);
} catch (e) {
log(`Failed to read extents of focused component: ${e.message}`);
return;
}
@ -817,8 +813,8 @@ var ZoomRegion = class ZoomRegion {
let extents;
try {
extents = text.get_character_extents(text.get_caret_offset(), 0);
} catch(e) {
log('Failed to read extents of text caret: ' + e.message);
} catch (e) {
log(`Failed to read extents of text caret: ${e.message}`);
return;
}
@ -1030,7 +1026,7 @@ var ZoomRegion = class ZoomRegion {
viewPort.x = 0;
viewPort.y = 0;
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
viewPort.height = global.screen_height / 2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.TOP_HALF;
}
@ -1042,9 +1038,9 @@ var ZoomRegion = class ZoomRegion {
setBottomHalf() {
let viewPort = {};
viewPort.x = 0;
viewPort.y = global.screen_height/2;
viewPort.y = global.screen_height / 2;
viewPort.width = global.screen_width;
viewPort.height = global.screen_height/2;
viewPort.height = global.screen_height / 2;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF;
}
@ -1057,7 +1053,7 @@ var ZoomRegion = class ZoomRegion {
let viewPort = {};
viewPort.x = 0;
viewPort.y = 0;
viewPort.width = global.screen_width/2;
viewPort.width = global.screen_width / 2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.LEFT_HALF;
@ -1069,9 +1065,9 @@ var ZoomRegion = class ZoomRegion {
*/
setRightHalf() {
let viewPort = {};
viewPort.x = global.screen_width/2;
viewPort.x = global.screen_width / 2;
viewPort.y = 0;
viewPort.width = global.screen_width/2;
viewPort.width = global.screen_width / 2;
viewPort.height = global.screen_height;
this._setViewPort(viewPort);
this._screenPosition = GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF;
@ -1103,21 +1099,21 @@ var ZoomRegion = class ZoomRegion {
*/
setScreenPosition(inPosition) {
switch (inPosition) {
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.FULL_SCREEN:
this.setFullScreenMode();
break;
case GDesktopEnums.MagnifierScreenPosition.TOP_HALF:
this.setTopHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.BOTTOM_HALF:
this.setBottomHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.LEFT_HALF:
this.setLeftHalf();
break;
case GDesktopEnums.MagnifierScreenPosition.RIGHT_HALF:
this.setRightHalf();
break;
}
}
@ -1460,11 +1456,9 @@ var ZoomRegion = class ZoomRegion {
if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PROPORTIONAL) {
return this._centerFromPointProportional(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
} else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.PUSH) {
return this._centerFromPointPush(xMouse, yMouse);
}
else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
} else if (this._mouseTrackingMode == GDesktopEnums.MagnifierMouseTrackingMode.CENTERED) {
return this._centerFromPointCentered(xMouse, yMouse);
}
@ -1532,7 +1526,7 @@ var ZoomRegion = class ZoomRegion {
let xProportion = (xPoint - halfScreenWidth) / halfScreenWidth; // -1 ... 1
let yProportion = (yPoint - halfScreenHeight) / halfScreenHeight; // -1 ... 1
let xPos = xPoint - xProportion * (widthRoi / 2 - xPadding);
let yPos = yPoint - yProportion * (heightRoi /2 - yPadding);
let yPos = yPoint - yProportion * (heightRoi / 2 - yPadding);
return [xPos, yPos];
}
@ -1634,7 +1628,7 @@ var Crosshairs = class Crosshairs {
this.reCenter();
}
/**
/**
* addToZoomRegion
* Either add the crosshairs actor to the given ZoomRegion, or, if it is
* already part of some other ZoomRegion, create a clone of the crosshairs
@ -1662,7 +1656,7 @@ var Crosshairs = class Crosshairs {
container.raise_child(magnifiedMouse, crosshairsActor);
let [xMouse, yMouse] = magnifiedMouse.get_position();
let [crosshairsWidth, crosshairsHeight] = crosshairsActor.get_size();
crosshairsActor.set_position(xMouse - crosshairsWidth / 2 , yMouse - crosshairsHeight / 2);
crosshairsActor.set_position(xMouse - crosshairsWidth / 2, yMouse - crosshairsHeight / 2);
}
}
return crosshairsActor;
@ -1778,13 +1772,12 @@ var Crosshairs = class Crosshairs {
// mouse.
this._clipSize = size;
this.reCenter();
}
else {
} else {
// Restore the missing chunk.
this._clipSize = [0, 0];
this.reCenter();
}
}
}
/**
* show:
@ -1818,9 +1811,7 @@ var Crosshairs = class Crosshairs {
reCenter(clipSize) {
let [groupWidth, groupHeight] = this._actor.get_size();
let leftLength = this._horizLeftHair.get_width();
let rightLength = this._horizRightHair.get_width();
let topLength = this._vertTopHair.get_height();
let bottomLength = this._vertBottomHair.get_height();
let thickness = this._horizLeftHair.get_height();
// Deal with clip rectangle.
@ -1927,8 +1918,8 @@ var MagShaderEffects = class MagShaderEffects {
// a null first argument.
let [bRed, bGreen, bBlue] = this._brightnessContrast.get_brightness();
this._brightnessContrast.set_enabled(
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
cRed != NO_CHANGE || cGreen != NO_CHANGE || cBlue != NO_CHANGE ||
bRed != NO_CHANGE || bGreen != NO_CHANGE || bBlue != NO_CHANGE
);
}
};

View File

@ -85,7 +85,7 @@ var ShellMagnifier = class ShellMagnifier {
let ROI = { x: roi[0], y: roi[1], width: roi[2] - roi[0], height: roi[3] - roi[1] };
let viewBox = { x: viewPort[0], y: viewPort[1], width: viewPort[2] - viewPort[0], height: viewPort[3] - viewPort[1] };
let realZoomRegion = Main.magnifier.createZoomRegion(xMagFactor, yMagFactor, ROI, viewBox);
let objectPath = ZOOM_SERVICE_PATH + '/zoomer' + _zoomRegionInstanceCount;
let objectPath = `${ZOOM_SERVICE_PATH}/zoomer${_zoomRegionInstanceCount}`;
_zoomRegionInstanceCount++;
let zoomRegionProxy = new ShellMagnifierZoomRegion(objectPath, realZoomRegion);
@ -106,9 +106,9 @@ var ShellMagnifier = class ShellMagnifier {
if (proxyAndZoomRegion && proxyAndZoomRegion.zoomRegion) {
Main.magnifier.addZoomRegion(proxyAndZoomRegion.zoomRegion);
return true;
}
else
} else {
return false;
}
}
/**
@ -179,74 +179,74 @@ var ShellMagnifier = class ShellMagnifier {
* Set the crosswire size of all ZoomRegions.
* @size: The thickness of each line in the cross wire.
*/
setCrosswireSize(size) {
setCrosswireSize(size) {
Main.magnifier.setCrosshairsThickness(size);
}
}
/**
* getCrosswireSize:
* Get the crosswire size of all ZoomRegions.
* @return: The thickness of each line in the cross wire.
*/
getCrosswireSize() {
getCrosswireSize() {
return Main.magnifier.getCrosshairsThickness();
}
}
/**
* setCrosswireLength:
* Set the crosswire length of all zoom-regions..
* @size: The length of each line in the cross wire.
*/
setCrosswireLength(length) {
setCrosswireLength(length) {
Main.magnifier.setCrosshairsLength(length);
}
}
/**
* setCrosswireSize:
* Set the crosswire size of all zoom-regions.
* @size: The thickness of each line in the cross wire.
*/
getCrosswireLength() {
getCrosswireLength() {
return Main.magnifier.getCrosshairsLength();
}
}
/**
* setCrosswireClip:
* Set if the crosswire will be clipped by the cursor image..
* @clip: Flag to indicate whether to clip the crosswire.
*/
setCrosswireClip(clip) {
setCrosswireClip(clip) {
Main.magnifier.setCrosshairsClip(clip);
}
}
/**
* getCrosswireClip:
* Get the crosswire clip value.
* @return: Whether the crosswire is clipped by the cursor image.
*/
getCrosswireClip() {
getCrosswireClip() {
return Main.magnifier.getCrosshairsClip();
}
}
/**
* setCrosswireColor:
* Set the crosswire color of all ZoomRegions.
* @color: Unsigned int of the form rrggbbaa.
*/
setCrosswireColor(color) {
setCrosswireColor(color) {
Main.magnifier.setCrosshairsColor('#%08x'.format(color));
}
}
/**
* getCrosswireClip:
* Get the crosswire color of all ZoomRegions.
* @return: The crosswire color as an unsigned int in the form rrggbbaa.
*/
getCrosswireColor() {
getCrosswireColor() {
let colorString = Main.magnifier.getCrosshairsColor();
// Drop the leading '#'.
return parseInt(colorString.slice(1), 16);
}
}
};
/**

View File

@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Clutter, Gio, GLib, Meta, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const AccessDialog = imports.ui.accessDialog;
@ -37,12 +37,16 @@ const WindowManager = imports.ui.windowManager;
const Magnifier = imports.ui.magnifier;
const XdndHandler = imports.ui.xdndHandler;
const KbdA11yDialog = imports.ui.kbdA11yDialog;
const LocatePointer = imports.ui.locatePointer;
const PointerA11yTimeout = imports.ui.pointerA11yTimeout;
const A11Y_SCHEMA = 'org.gnome.desktop.a11y.keyboard';
const STICKY_KEYS_ENABLE = 'stickykeys-enable';
const LOG_DOMAIN = 'GNOME Shell';
const GNOMESHELL_STARTED_MESSAGE_ID = 'f3ea493c22934e26811cd62abe8e203a';
var componentManager = null;
var extensionManager = null;
var panel = null;
var overview = null;
var runDialog = null;
@ -74,6 +78,7 @@ var layoutManager = null;
var kbdA11yDialog = null;
var inputMethod = null;
var introspectService = null;
var locatePointer = null;
let _startDate;
let _defaultCssStylesheet = null;
let _cssStylesheet = null;
@ -92,6 +97,8 @@ function _sessionUpdated() {
wm.allowKeybinding('overlay-key', Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW);
wm.allowKeybinding('locate-pointer-key', Shell.ActionMode.ALL);
wm.setCustomKeybindingHandler('panel-run-dialog',
Shell.ActionMode.NORMAL |
Shell.ActionMode.OVERVIEW,
@ -133,12 +140,12 @@ function start() {
function _initializeUI() {
// Ensure ShellWindowTracker and ShellAppUsage are initialized; this will
// also initialize ShellAppSystem first. ShellAppSystem
// also initialize ShellAppSystem first. ShellAppSystem
// needs to load all the .desktop files, and ShellWindowTracker
// will use those to associate with windows. Right now
// will use those to associate with windows. Right now
// the Monitor doesn't listen for installed app changes
// and recalculate application associations, so to avoid
// races for now we initialize it here. It's better to
// races for now we initialize it here. It's better to
// be predictable anyways.
Shell.WindowTracker.get_default();
Shell.AppUsage.get_default();
@ -150,8 +157,8 @@ function _initializeUI() {
// Setup the stage hierarchy early
layoutManager = new Layout.LayoutManager();
// Various parts of the codebase still refers to Main.uiGroup
// instead using the layoutManager. This keeps that code
// Various parts of the codebase still refer to Main.uiGroup
// instead of using the layoutManager. This keeps that code
// working until it's updated.
uiGroup = layoutManager.uiGroup;
@ -165,6 +172,8 @@ function _initializeUI() {
kbdA11yDialog = new KbdA11yDialog.KbdA11yDialog();
wm = new WindowManager.WindowManager();
magnifier = new Magnifier.Magnifier();
locatePointer = new LocatePointer.LocatePointer();
if (LoginManager.canLock())
screenShield = new ScreenShield.ScreenShield();
@ -183,6 +192,8 @@ function _initializeUI() {
layoutManager.init();
overview.init();
(new PointerA11yTimeout.PointerA11yTimeout());
_a11ySettings = new Gio.Settings({ schema_id: A11Y_SCHEMA });
global.display.connect('overlay-key', () => {
@ -190,6 +201,10 @@ function _initializeUI() {
overview.toggle();
});
global.connect('locate-pointer', () => {
locatePointer.show();
});
global.display.connect('show-restart-message', (display, message) => {
showRestartMessage(message);
return true;
@ -212,7 +227,8 @@ function _initializeUI() {
_startDate = new Date();
ExtensionDownloader.init();
ExtensionSystem.init();
extensionManager = new ExtensionSystem.ExtensionManager();
extensionManager.init();
if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', () => {
@ -229,14 +245,18 @@ function _initializeUI() {
}
if (sessionMode.currentMode != 'gdm' &&
sessionMode.currentMode != 'initial-setup') {
Shell.Global.log_structured('GNOME Shell started at ' + _startDate,
['MESSAGE_ID=' + GNOMESHELL_STARTED_MESSAGE_ID]);
GLib.log_structured(LOG_DOMAIN, GLib.LogLevelFlags.LEVEL_MESSAGE, {
'MESSAGE': `GNOME Shell started at ${_startDate}`,
'MESSAGE_ID': GNOMESHELL_STARTED_MESSAGE_ID
});
}
LoginManager.registerSessionWithGDM();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
let perfOutput = GLib.getenv("SHELL_PERF_OUTPUT");
let module = eval('imports.perf.' + perfModuleName + ';');
let module = eval(`imports.perf.${perfModuleName};`);
Scripting.runPerfScript(module, perfOutput);
}
});
@ -303,7 +323,7 @@ function getThemeStylesheet() {
/**
* setThemeStylesheet:
* @cssStylesheet: A file path that contains the theme CSS,
* set it to null to use the default
* set it to null to use the default
*
* Set the theme CSS file that the shell will load
*/
@ -372,9 +392,9 @@ function notify(msg, details) {
function notifyError(msg, details) {
// Also print to stderr so it's logged somewhere
if (details)
log('error: ' + msg + ': ' + details);
log(`error: ${msg}: ${details}`);
else
log('error: ' + msg);
log(`error: ${msg}`);
notify(msg, details);
}
@ -403,15 +423,15 @@ function _findModal(actor) {
*
* @params may be used to provide the following parameters:
* - timestamp: used to associate the call with a specific user initiated
* event. If not provided then the value of
* event. If not provided then the value of
* global.get_current_time() is assumed.
*
* - options: Meta.ModalOptions flags to indicate that the pointer is
* already grabbed
*
* - actionMode: used to set the current Shell.ActionMode to filter
* global keybindings; the default of NONE will filter
* out all keybindings
* global keybindings; the default of NONE will filter
* out all keybindings
*
* Returns: true iff we successfully acquired a grab or already had one
*/
@ -457,15 +477,15 @@ function pushModal(actor, params) {
/**
* popModal:
* @actor: #ClutterActor passed to original invocation of pushModal().
* @actor: #ClutterActor passed to original invocation of pushModal()
* @timestamp: optional timestamp
*
* Reverse the effect of pushModal(). If this invocation is undoing
* Reverse the effect of pushModal(). If this invocation is undoing
* the topmost invocation, then the focus will be restored to the
* previous focus at the time when pushModal() was invoked.
*
* @timestamp is optionally used to associate the call with a specific user
* initiated event. If not provided then the value of
* initiated event. If not provided then the value of
* global.get_current_time() is assumed.
*/
function popModal(actor, timestamp) {
@ -627,7 +647,7 @@ function _queueBeforeRedraw(workId) {
*
* This function sets up a callback to be invoked when either the
* given actor is mapped, or after some period of time when the machine
* is idle. This is useful if your actor isn't always visible on the
* is idle. This is useful if your actor isn't always visible on the
* screen (for example, all actors in the overview), and you don't want
* to consume resources updating if the actor isn't actually going to be
* displaying to the user.
@ -640,11 +660,11 @@ function _queueBeforeRedraw(workId) {
*/
function initializeDeferredWork(actor, callback, props) {
// Turn into a string so we can use as an object property
let workId = '' + (++_deferredWorkSequence);
let workId = `${(++_deferredWorkSequence)}`;
_deferredWorkData[workId] = { 'actor': actor,
'callback': callback };
actor.connect('notify::mapped', () => {
if (!(actor.mapped && _deferredWorkQueue.indexOf(workId) >= 0))
if (!(actor.mapped && _deferredWorkQueue.includes(workId)))
return;
_queueBeforeRedraw(workId);
});
@ -663,7 +683,7 @@ function initializeDeferredWork(actor, callback, props) {
* @workId: work identifier
*
* Ensure that the work identified by @workId will be
* run on map or timeout. You should call this function
* run on map or timeout. You should call this function
* for example when data being displayed by the actor has
* changed.
*/
@ -674,7 +694,7 @@ function queueDeferredWork(workId) {
logError(new Error(message), message);
return;
}
if (_deferredWorkQueue.indexOf(workId) < 0)
if (!_deferredWorkQueue.includes(workId))
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);
@ -689,12 +709,13 @@ function queueDeferredWork(workId) {
}
}
var RestartMessage = class extends ModalDialog.ModalDialog {
constructor(message) {
super({ shellReactive: true,
styleClass: 'restart-message headline',
shouldFadeIn: false,
destroyOnClose: true });
var RestartMessage = GObject.registerClass(
class RestartMessage extends ModalDialog.ModalDialog {
_init(message) {
super._init({ shellReactive: true,
styleClass: 'restart-message headline',
shouldFadeIn: false,
destroyOnClose: true });
let label = new St.Label({ text: message });
@ -704,7 +725,7 @@ var RestartMessage = class extends ModalDialog.ModalDialog {
y_align: St.Align.MIDDLE });
this.buttonLayout.hide();
}
};
});
function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);

View File

@ -33,9 +33,7 @@ function _fixMarkup(text, allowMarkup) {
}
var URLHighlighter = class URLHighlighter {
constructor(text, lineWrap, allowMarkup) {
if (!text)
text = '';
constructor(text = '', lineWrap, allowMarkup) {
this.actor = new St.Label({ reactive: true, style_class: 'url-highlighter',
x_expand: true, x_align: Clutter.ActorAlign.START });
this._linkColor = '#ccccff';
@ -72,7 +70,7 @@ var URLHighlighter = class URLHighlighter {
let urlId = this._findUrlAtPos(event);
if (urlId != -1) {
let url = this._urls[urlId].url;
if (url.indexOf(':') == -1)
if (!url.includes(':'))
url = 'http://' + url;
Gio.app_info_launch_default_for_uri(url, global.create_app_launch_context(0, -1));
@ -135,18 +133,18 @@ var URLHighlighter = class URLHighlighter {
let success;
let [x, y] = event.get_coords();
[success, x, y] = this.actor.transform_stage_point(x, y);
let find_pos = -1;
let findPos = -1;
for (let i = 0; i < this.actor.clutter_text.text.length; i++) {
let [success, px, py, line_height] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + line_height < y || x < px)
let [success, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + lineHeight < y || x < px)
continue;
find_pos = i;
findPos = i;
}
if (find_pos != -1) {
if (findPos != -1) {
for (let i = 0; i < this._urls.length; i++)
if (find_pos >= this._urls[i].pos &&
this._urls[i].pos + this._urls[i].url.length > find_pos)
return i;
if (findPos >= this._urls[i].pos &&
this._urls[i].pos + this._urls[i].url.length > findPos)
return i;
}
return -1;
}
@ -197,12 +195,14 @@ class ScaleLayout extends Clutter.BinLayout {
});
var LabelExpanderLayout = GObject.registerClass({
Properties: { 'expansion': GObject.ParamSpec.double('expansion',
'Expansion',
'Expansion of the layout, between 0 (collapsed) ' +
'and 1 (fully expanded',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
0, 1, 0)},
Properties: {
'expansion': GObject.ParamSpec.double('expansion',
'Expansion',
'Expansion of the layout, between 0 (collapsed) ' +
'and 1 (fully expanded',
GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE,
0, 1, 0)
},
}, class LabelExpanderLayout extends Clutter.LayoutManager {
_init(params) {
this._expansion = 0;
@ -467,11 +467,10 @@ var Message = class Message {
{ scale_y: 0,
time: MessageTray.ANIMATION_TIME,
transition: 'easeOutQuad',
onCompleteScope: this,
onComplete() {
onComplete: () => {
this._actionBin.hide();
this.expanded = false;
}});
} });
} else {
this._bodyStack.layout_manager.expansion = 0;
this._actionBin.scale_y = 0;
@ -626,7 +625,7 @@ var MessageListSection = class MessageListSection {
onComplete() {
obj.container.destroy();
global.sync_pointer();
}});
} });
} else {
obj.container.destroy();
global.sync_pointer();
@ -656,7 +655,7 @@ var MessageListSection = class MessageListSection {
transition: 'easeOutQuad',
onComplete() {
message.close();
}});
} });
}
}
}

View File

@ -218,17 +218,17 @@ class NotificationApplicationPolicy extends NotificationPolicy {
this._masterSettings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications' });
this._settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.notifications.application',
path: '/org/gnome/desktop/notifications/application/' + this._canonicalId + '/' });
path: `/org/gnome/desktop/notifications/application/${this._canonicalId}/` });
this._masterSettings.connect('changed', this._changed.bind(this));
this._settings.connect('changed', this._changed.bind(this));
}
store() {
this._settings.set_string('application-id', this.id + '.desktop');
this._settings.set_string('application-id', `${this.id}.desktop`);
let apps = this._masterSettings.get_strv('application-children');
if (apps.indexOf(this._canonicalId) < 0) {
if (!apps.includes(this._canonicalId)) {
apps.push(this._canonicalId);
this._masterSettings.set_strv('application-children', apps);
}
@ -248,7 +248,7 @@ class NotificationApplicationPolicy extends NotificationPolicy {
_canonicalizeId(id) {
// Keys are restricted to lowercase alphanumeric characters and dash,
// and two dashes cannot be in succession
return id.toLowerCase().replace(/[^a-z0-9\-]/g, '-').replace(/--+/g, '-');
return id.toLowerCase().replace(/[^a-z0-9-]/g, '-').replace(/--+/g, '-');
}
get enable() {
@ -473,9 +473,7 @@ var Notification = class Notification {
this.destroy();
}
destroy(reason) {
if (!reason)
reason = NotificationDestroyedReason.DISMISSED;
destroy(reason = NotificationDestroyedReason.DISMISSED) {
this.emit('destroy', reason);
}
};
@ -590,11 +588,11 @@ class SourceActor extends St.Widget {
});
this._actorDestroyed = false;
let scale_factor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
this._iconBin = new St.Bin({ x_fill: true,
x_expand: true,
height: size * scale_factor,
width: size * scale_factor });
height: size * scaleFactor,
width: size * scaleFactor });
this.add_actor(this._iconBin);
@ -772,7 +770,7 @@ var Source = class Source {
}
pushNotification(notification) {
if (this.notifications.indexOf(notification) >= 0)
if (this.notifications.includes(notification))
return;
while (this.notifications.length >= MAX_NOTIFICATIONS_PER_SOURCE)
@ -988,7 +986,7 @@ var MessageTray = class MessageTray {
add(source) {
if (this.contains(source)) {
log('Trying to re-add source ' + source.title);
log(`Trying to re-add source ${source.title}`);
return;
}
@ -1069,7 +1067,7 @@ var MessageTray = class MessageTray {
// If a new notification is updated while it is being hidden,
// we stop hiding it and show it again.
this._updateShowingNotification();
} else if (this._notificationQueue.indexOf(notification) < 0) {
} else if (!this._notificationQueue.includes(notification)) {
// If the queue is "full", we skip banner mode and just show a small
// indicator in the panel; however do make an exception for CRITICAL
// notifications, as only banner mode allows expansion.
@ -1167,7 +1165,7 @@ var MessageTray = class MessageTray {
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT * 1000,
this._onNotificationLeftTimeout.bind(this));
this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else {
this._notificationLeftTimeoutId = 0;

View File

@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Atk, Clutter, Shell, St } = imports.gi;
const Signals = imports.signals;
const { Atk, Clutter, GObject, Shell, St } = imports.gi;
const Dialog = imports.ui.dialog;
const Layout = imports.ui.layout;
@ -21,8 +20,22 @@ var State = {
FADED_OUT: 4
};
var ModalDialog = class {
constructor(params) {
var ModalDialog = GObject.registerClass({
Properties: {
'state': GObject.ParamSpec.int('state', 'Dialog state', 'state',
GObject.ParamFlags.READABLE,
Math.min(...Object.values(State)),
Math.max(...Object.values(State)),
State.CLOSED)
},
Signals: { 'opened': {}, 'closed': {} }
}, class ModalDialog extends St.Widget {
_init(params) {
super._init({ visible: false,
x: 0,
y: 0,
accessible_role: Atk.Role.DIALOG });
params = Params.parse(params, { shellReactive: false,
styleClass: null,
actionMode: Shell.ActionMode.SYSTEM_MODAL,
@ -30,7 +43,7 @@ var ModalDialog = class {
shouldFadeOut: true,
destroyOnClose: true });
this.state = State.CLOSED;
this._state = State.CLOSED;
this._hasModal = false;
this._actionMode = params.actionMode;
this._shellReactive = params.shellReactive;
@ -38,31 +51,25 @@ var ModalDialog = class {
this._shouldFadeOut = params.shouldFadeOut;
this._destroyOnClose = params.destroyOnClose;
this._group = new St.Widget({ visible: false,
x: 0,
y: 0,
accessible_role: Atk.Role.DIALOG });
Main.layoutManager.modalDialogGroup.add_actor(this._group);
Main.layoutManager.modalDialogGroup.add_actor(this);
let constraint = new Clutter.BindConstraint({ source: global.stage,
coordinate: Clutter.BindCoordinate.ALL });
this._group.add_constraint(constraint);
this._group.connect('destroy', this._onGroupDestroy.bind(this));
this.add_constraint(constraint);
this.backgroundStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._backgroundBin = new St.Bin({ child: this.backgroundStack,
x_fill: true, y_fill: true });
this._monitorConstraint = new Layout.MonitorConstraint();
this._backgroundBin.add_constraint(this._monitorConstraint);
this._group.add_actor(this._backgroundBin);
this.add_actor(this._backgroundBin);
this.dialogLayout = new Dialog.Dialog(this.backgroundStack, params.styleClass);
this.contentLayout = this.dialogLayout.contentLayout;
this.buttonLayout = this.dialogLayout.buttonLayout;
if (!this._shellReactive) {
this._lightbox = new Lightbox.Lightbox(this._group,
this._lightbox = new Lightbox.Lightbox(this,
{ inhibitEvents: true,
radialEffect: true });
this._lightbox.highlight(this._backgroundBin);
@ -77,8 +84,16 @@ var ModalDialog = class {
this._savedKeyFocus = null;
}
destroy() {
this._group.destroy();
get state() {
return this._state;
}
_setState(state) {
if (this._state == state)
return;
this._state = state;
this.notify('state');
}
clearButtons() {
@ -96,29 +111,25 @@ var ModalDialog = class {
return this.dialogLayout.addButton(buttonInfo);
}
_onGroupDestroy() {
this.emit('destroy');
}
_fadeOpen(onPrimary) {
if (onPrimary)
this._monitorConstraint.primary = true;
else
this._monitorConstraint.index = global.display.get_current_monitor();
this.state = State.OPENING;
this._setState(State.OPENING);
this.dialogLayout.opacity = 255;
if (this._lightbox)
this._lightbox.show();
this._group.opacity = 0;
this._group.show();
Tweener.addTween(this._group,
this.opacity = 0;
this.show();
Tweener.addTween(this,
{ opacity: 255,
time: this._shouldFadeIn ? OPEN_AND_CLOSE_TIME : 0,
transition: 'easeOutQuad',
onComplete: () => {
this.state = State.OPENED;
this._setState(State.OPENED);
this.emit('opened');
}
});
@ -148,8 +159,8 @@ var ModalDialog = class {
}
_closeComplete() {
this.state = State.CLOSED;
this._group.hide();
this._setState(State.CLOSED);
this.hide();
this.emit('closed');
if (this._destroyOnClose)
@ -160,17 +171,17 @@ var ModalDialog = class {
if (this.state == State.CLOSED || this.state == State.CLOSING)
return;
this.state = State.CLOSING;
this._setState(State.CLOSING);
this.popModal(timestamp);
this._savedKeyFocus = null;
if (this._shouldFadeOut)
Tweener.addTween(this._group,
Tweener.addTween(this,
{ opacity: 0,
time: OPEN_AND_CLOSE_TIME,
transition: 'easeOutQuad',
onComplete: this._closeComplete.bind(this)
})
});
else
this._closeComplete();
}
@ -183,11 +194,11 @@ var ModalDialog = class {
return;
let focus = global.stage.key_focus;
if (focus && this._group.contains(focus))
if (focus && this.contains(focus))
this._savedKeyFocus = focus;
else
this._savedKeyFocus = null;
Main.popModal(this._group, timestamp);
Main.popModal(this, timestamp);
this._hasModal = false;
if (!this._shellReactive)
@ -201,7 +212,7 @@ var ModalDialog = class {
let params = { actionMode: this._actionMode };
if (timestamp)
params['timestamp'] = timestamp;
if (!Main.pushModal(this._group, params))
if (!Main.pushModal(this, params))
return false;
this._hasModal = true;
@ -239,12 +250,11 @@ var ModalDialog = class {
this.popModal(timestamp);
Tweener.addTween(this.dialogLayout,
{ opacity: 0,
time: FADE_OUT_DIALOG_TIME,
time: FADE_OUT_DIALOG_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this.state = State.FADED_OUT;
this._setState(State.FADED_OUT);
}
});
}
};
Signals.addSignalMethods(ModalDialog.prototype);
});

View File

@ -135,7 +135,7 @@ var MprisPlayer = class MprisPlayer {
// so prefer activating the app via .desktop file if possible
let app = null;
if (this._mprisProxy.DesktopEntry) {
let desktopId = this._mprisProxy.DesktopEntry + '.desktop';
let desktopId = `${this._mprisProxy.DesktopEntry}.desktop`;
app = Shell.AppSystem.get_default().lookup_app(desktopId);
}

View File

@ -76,13 +76,13 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
_fallbackIconForNotificationData(hints) {
let stockIcon;
switch (hints.urgency) {
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'dialog-information';
break;
case Urgency.CRITICAL:
stockIcon = 'dialog-error';
break;
case Urgency.LOW:
case Urgency.NORMAL:
stockIcon = 'dialog-information';
break;
case Urgency.CRITICAL:
stockIcon = 'dialog-error';
break;
}
return new Gio.ThemedIcon({ name: stockIcon });
}
@ -170,11 +170,11 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = this._nextNotificationId++;
let idle_id = Mainloop.idle_add(() => {
let idleId = Mainloop.idle_add(() => {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(idle_id, '[gnome-shell] this._emitNotificationClosed');
GLib.Source.set_name_by_id(idleId, '[gnome-shell] this._emitNotificationClosed');
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
@ -231,7 +231,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// There's already a pending call to GetConnectionUnixProcessID,
// which will see the new notification data when it finishes,
// so we don't have to do anything.
return invocation.return_value(GLib.Variant.new('(u)', [id]));;
return invocation.return_value(GLib.Variant.new('(u)', [id]));
}
this._busProxy.GetConnectionUnixProcessIDRemote(sender, (result, excp) => {
@ -270,15 +270,15 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
delete this._notifications[ndata.id];
let notificationClosedReason;
switch (reason) {
case MessageTray.NotificationDestroyedReason.EXPIRED:
notificationClosedReason = NotificationClosedReason.EXPIRED;
break;
case MessageTray.NotificationDestroyedReason.DISMISSED:
notificationClosedReason = NotificationClosedReason.DISMISSED;
break;
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
break;
case MessageTray.NotificationDestroyedReason.EXPIRED:
notificationClosedReason = NotificationClosedReason.EXPIRED;
break;
case MessageTray.NotificationDestroyedReason.DISMISSED:
notificationClosedReason = NotificationClosedReason.DISMISSED;
break;
case MessageTray.NotificationDestroyedReason.SOURCE_CLOSED:
notificationClosedReason = NotificationClosedReason.APP_CLOSED;
break;
}
this._emitNotificationClosed(ndata.id, notificationClosedReason);
});
@ -309,7 +309,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
if (actions.length) {
for (let i = 0; i < actions.length - 1; i += 2) {
let [actionId, label] = [actions[i], actions[i+1]];
let [actionId, label] = [actions[i], actions[i + 1]];
if (actionId == 'default')
hasDefaultAction = true;
else
@ -330,15 +330,15 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
switch (hints.urgency) {
case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
break;
case Urgency.NORMAL:
notification.setUrgency(MessageTray.Urgency.NORMAL);
break;
case Urgency.CRITICAL:
notification.setUrgency(MessageTray.Urgency.CRITICAL);
break;
case Urgency.LOW:
notification.setUrgency(MessageTray.Urgency.LOW);
break;
case Urgency.NORMAL:
notification.setUrgency(MessageTray.Urgency.NORMAL);
break;
case Urgency.CRITICAL:
notification.setUrgency(MessageTray.Urgency.CRITICAL);
break;
}
notification.setResident(!!hints.resident);
// 'transient' is a reserved keyword in JS, so we have to retrieve the value
@ -437,7 +437,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
_createPolicy() {
if (this.app && this.app.get_app_info()) {
let id = this.app.get_id().replace(/\.desktop$/,'');
let id = this.app.get_id().replace(/\.desktop$/, '');
return new MessageTray.NotificationApplicationPolicy(id);
} else {
return new MessageTray.NotificationGenericPolicy();
@ -474,7 +474,7 @@ class FdoNotificationDaemonSource extends MessageTray.Source {
return app;
if (appId) {
app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
app = Shell.AppSystem.get_default().lookup_app(`${appId}.desktop`);
if (app != null)
return app;
}
@ -573,7 +573,7 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
this.update(title.unpack(), body ? body.unpack() : null,
{ gicon: gicon ? Gio.icon_deserialize(gicon) : null,
datetime : time ? GLib.DateTime.new_from_unix_local(time.unpack()) : null });
datetime: time ? GLib.DateTime.new_from_unix_local(time.unpack()) : null });
}
_activateAction(namespacedActionId, target) {
@ -610,7 +610,7 @@ function objectPathFromAppId(appId) {
}
function getPlatformData() {
let startupId = GLib.Variant.new('s', '_TIME' + global.get_current_time());
let startupId = GLib.Variant.new('s', `_TIME${global.get_current_time()}`);
return { "desktop-startup-id": startupId };
}
@ -623,7 +623,7 @@ class GtkNotificationDaemonAppSource extends MessageTray.Source {
if (!GLib.Variant.is_object_path(objectPath))
throw new InvalidAppError();
let app = Shell.AppSystem.get_default().lookup_app(appId + '.desktop');
let app = Shell.AppSystem.get_default().lookup_app(`${appId}.desktop`);
if (!app)
throw new InvalidAppError();
@ -759,7 +759,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
let source;
try {
source = this._ensureAppSource(appId);
} catch(e) {
} catch (e) {
if (e instanceof InvalidAppError)
return;
throw e;
@ -793,7 +793,7 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
let source;
try {
source = this._ensureAppSource(appId);
} catch(e) {
} catch (e) {
if (e instanceof InvalidAppError) {
invocation.return_dbus_error('org.gtk.Notifications.InvalidApp', 'The app by ID "%s" could not be found'.format(appId));
return;

View File

@ -4,8 +4,6 @@ const { Clutter, Gio, Meta, St } = imports.gi;
const Main = imports.ui.main;
var FADE_TIME = 0.1;
var OsdMonitorLabel = class {
constructor(monitor, label) {
this._actor = new St.Widget({ x_expand: true,
@ -53,7 +51,7 @@ var OsdMonitorLabeler = class {
this._osdLabels = [];
this._monitorLabels = null;
Main.layoutManager.connect('monitors-changed',
this._reset.bind(this));
this._reset.bind(this));
this._reset();
}

View File

@ -21,7 +21,7 @@ var LevelBar = class extends BarLevel.BarLevel {
this.actor.accessible_name = _("Volume");
this.actor.connect('notify::width', () => { this.level = this.level; });
this.actor.connect('notify::width', () => this.level = this.level);
}
get level() {
@ -151,9 +151,7 @@ var OsdWindow = class {
}
}
setMaxLevel(maxLevel) {
if (maxLevel === undefined)
maxLevel = 100;
setMaxLevel(maxLevel = 100) {
this._level.maxLevel = maxLevel;
}
@ -195,8 +193,8 @@ var OsdWindow = class {
time: FADE_TIME,
transition: 'easeOutQuad',
onComplete: () => {
this._reset();
Meta.enable_unredirect_for_display(global.display);
this._reset();
Meta.enable_unredirect_for_display(global.display);
}
});
return GLib.SOURCE_REMOVE;
@ -231,7 +229,7 @@ var OsdWindowManager = class {
constructor() {
this._osdWindows = [];
Main.layoutManager.connect('monitors-changed',
this._monitorsChanged.bind(this));
this._monitorsChanged.bind(this));
this._monitorsChanged();
}

View File

@ -424,12 +424,12 @@ var Overview = class {
}
fadeInDesktop() {
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
this._desktopFade.opacity = 0;
this._desktopFade.show();
Tweener.addTween(this._desktopFade,
{ opacity: 255,
time: ANIMATION_TIME,
transition: 'easeOutQuad' });
}
fadeOutDesktop() {

View File

@ -18,7 +18,7 @@ function getRtlSlideDirection(direction, actor) {
SlideDirection.RIGHT : SlideDirection.LEFT;
return direction;
};
}
var SlideDirection = {
LEFT: 0,
@ -133,7 +133,7 @@ var SlidingControl = class {
getVisibleWidth() {
let child = this.actor.get_first_child();
let [, , natWidth, ] = child.get_preferred_size();
let [, , natWidth] = child.get_preferred_size();
return natWidth;
}
@ -410,7 +410,7 @@ var ControlsManager = class {
x_expand: true, y_expand: true,
clip_to_allocation: true });
this._group = new St.BoxLayout({ name: 'overview-group',
x_expand: true, y_expand: true });
x_expand: true, y_expand: true });
this.actor.add_actor(this._group);
this.actor.add_actor(this._dashSlider.actor);

View File

@ -121,7 +121,7 @@ var ActionComboBox = class {
this.actor.set_child(box);
this._label = new St.Label({ style_class: 'combo-box-label' });
box.add_child(this._label)
box.add_child(this._label);
let arrow = new St.Icon({ style_class: 'popup-menu-arrow',
icon_name: 'pan-down-symbolic',
@ -186,7 +186,7 @@ var ActionComboBox = class {
}
setButtonActionsActive(active) {
this._buttonItems.forEach(item => { item.setSensitive(active); });
this._buttonItems.forEach(item => item.setSensitive(active));
}
};
Signals.addSignalMethods(ActionComboBox.prototype);
@ -208,7 +208,7 @@ var ActionEditor = class {
this._doneButton = new St.Button({ label: _("Done"),
style_class: 'button',
x_expand: false});
x_expand: false });
this._doneButton.connect('clicked', this._onEditingDone.bind(this));
this.actor.add_actor(this._doneButton);
}
@ -275,21 +275,23 @@ var ActionEditor = class {
Signals.addSignalMethods(ActionEditor.prototype);
var PadDiagram = GObject.registerClass({
Properties: { 'left-handed': GObject.ParamSpec.boolean('left-handed',
'left-handed', 'Left handed',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'image': GObject.ParamSpec.string('image', 'image', 'Image',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'editor-actor': GObject.ParamSpec.object('editor-actor',
'editor-actor',
'Editor actor',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
Clutter.Actor.$gtype) },
Properties: {
'left-handed': GObject.ParamSpec.boolean('left-handed',
'left-handed', 'Left handed',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
false),
'image': GObject.ParamSpec.string('image', 'image', 'Image',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
null),
'editor-actor': GObject.ParamSpec.object('editor-actor',
'editor-actor',
'Editor actor',
GObject.ParamFlags.READWRITE |
GObject.ParamFlags.CONSTRUCT_ONLY,
Clutter.Actor.$gtype)
},
}, class PadDiagram extends St.DrawingArea {
_init(params) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css');
@ -340,7 +342,7 @@ var PadDiagram = GObject.registerClass({
return ('<?xml version="1.0" encoding="UTF-8" standalone="no"?>' +
'<svg version="1.1" xmlns="http://www.w3.org/2000/svg" ' +
'xmlns:xi="http://www.w3.org/2001/XInclude" ' +
'width="' + this._imageWidth + '" height="' + this._imageHeight + '"> ' +
`width="${this._imageWidth}" height="${this._imageHeight}"> ` +
'<style type="text/css">');
}
@ -355,10 +357,10 @@ var PadDiagram = GObject.registerClass({
for (let i = 0; i < this._activeButtons.length; i++) {
let ch = String.fromCharCode('A'.charCodeAt() + this._activeButtons[i]);
css += ('.' + ch + ' { ' +
' stroke: ' + ACTIVE_COLOR + ' !important; ' +
' fill: ' + ACTIVE_COLOR + ' !important; ' +
'} ');
css += `.${ch} {
stroke: ${ACTIVE_COLOR} !important;
fill: ${ACTIVE_COLOR} !important;
}`;
}
return css;
@ -440,11 +442,11 @@ var PadDiagram = GObject.registerClass({
let cr = this.get_context();
cr.save();
cr.translate(width/2, height/2);
cr.translate(width / 2, height / 2);
cr.scale(this._scale, this._scale);
if (this._leftHanded)
cr.rotate(Math.PI);
cr.translate(-dimensions.width/2, -dimensions.height/2);
cr.translate(-dimensions.width / 2, -dimensions.height / 2);
this._handle.render_cairo(cr);
cr.restore();
cr.$dispose();
@ -457,7 +459,7 @@ var PadDiagram = GObject.registerClass({
// I miss Cairo.Matrix
let dimensions = this._handle.get_dimensions();
x = x * this._scale + this._actorWidth / 2 - dimensions.width / 2 * this._scale;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;;
y = y * this._scale + this._actorHeight / 2 - dimensions.height / 2 * this._scale;
return [Math.round(x), Math.round(y)];
}
@ -468,12 +470,12 @@ var PadDiagram = GObject.registerClass({
let leaderPos, leaderSize, pos;
let found, direction;
[found, pos] = this._handle.get_position_sub('#' + labelName);
[found, pos] = this._handle.get_position_sub(`#${labelName}`);
if (!found)
return [false];
[found, leaderPos] = this._handle.get_position_sub('#' + leaderName);
[found, leaderSize] = this._handle.get_dimensions_sub('#' + leaderName);
[found, leaderPos] = this._handle.get_position_sub(`#${leaderName}`);
[found, leaderSize] = this._handle.get_dimensions_sub(`#${leaderName}`);
if (!found)
return [false];
@ -488,15 +490,15 @@ var PadDiagram = GObject.registerClass({
pos.y = this._imageHeight - pos.y;
}
let [x, y] = this._transformPoint(pos.x, pos.y)
let [x, y] = this._transformPoint(pos.x, pos.y);
return [true, x, y, direction];
}
getButtonLabelCoords(button) {
let ch = String.fromCharCode('A'.charCodeAt() + button);
let labelName = 'Label' + ch;
let leaderName = 'Leader' + ch;
let labelName = `Label${ch}`;
let leaderName = `Leader${ch}`;
return this._getItemLabelCoords(labelName, leaderName);
}
@ -504,8 +506,8 @@ var PadDiagram = GObject.registerClass({
getRingLabelCoords(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == CW ? 'CW' : 'CCW';
let labelName = 'LabelRing' + numStr + dirStr;
let leaderName = 'LeaderRing' + numStr + dirStr;
let labelName = `LabelRing${numStr}${dirStr}`;
let leaderName = `LeaderRing${numStr}${dirStr}`;
return this._getItemLabelCoords(labelName, leaderName);
}
@ -513,8 +515,8 @@ var PadDiagram = GObject.registerClass({
getStripLabelCoords(number, dir) {
let numStr = number > 0 ? (number + 1).toString() : '';
let dirStr = dir == UP ? 'Up' : 'Down';
let labelName = 'LabelStrip' + numStr + dirStr;
let leaderName = 'LeaderStrip' + numStr + dirStr;
let labelName = `LabelStrip${numStr}${dirStr}`;
let leaderName = `LeaderStrip${numStr}${dirStr}`;
return this._getItemLabelCoords(labelName, leaderName);
}
@ -611,7 +613,7 @@ var PadDiagram = GObject.registerClass({
var PadOsd = class {
constructor(padDevice, settings, imagePath, editionMode, monitorIndex) {
this.padDevice = padDevice;
this._groupPads = [ padDevice ];
this._groupPads = [padDevice];
this._settings = settings;
this._imagePath = imagePath;
this._editionMode = editionMode;
@ -630,7 +632,7 @@ var PadOsd = class {
// If the device is being removed, destroy the padOsd.
if (device == this.padDevice) {
this.destroy();
} else if (this._groupPads.indexOf(device) != -1) {
} else if (this._groupPads.includes(device)) {
// Or update the pad chooser if the device belongs to
// the same group.
this._groupPads.splice(this._groupPads.indexOf(device), 1);
@ -714,9 +716,9 @@ var PadOsd = class {
}
let buttonBox = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
x_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER });
this.actor.add_actor(buttonBox);
this._editButton = new St.Button({ label: _("Edit…"),
style_class: 'button',
@ -734,7 +736,7 @@ var PadOsd = class {
_updatePadChooser() {
if (this._groupPads.length > 1) {
if (this._padChooser == null) {
this._padChooser = new PadChooser(this.padDevice, this._groupPads)
this._padChooser = new PadChooser(this.padDevice, this._groupPads);
this._padChooser.connect('pad-selected', (chooser, pad) => {
this._requestForOtherPad(pad);
});
@ -749,8 +751,7 @@ var PadOsd = class {
}
_requestForOtherPad(pad) {
if (pad == this.padDevice ||
this._groupPads.indexOf(pad) == -1)
if (pad == this.padDevice || !this._groupPads.includes(pad))
return;
let editionMode = this._editionMode;
@ -801,7 +802,7 @@ var PadOsd = class {
// If the event comes from another pad in the same group,
// show the OSD for it.
if (this._groupPads.indexOf(event.get_source_device()) != -1) {
if (this._groupPads.includes(event.get_source_device())) {
this._requestForOtherPad(event.get_source_device());
return Clutter.EVENT_STOP;
}
@ -865,7 +866,7 @@ var PadOsd = class {
if (this._followUpActionEdition(str))
return;
this._padDiagram.stopEdition(false, str ? str : _("None"))
this._padDiagram.stopEdition(false, str ? str : _("None"));
this._editedAction = null;
}
@ -888,7 +889,7 @@ var PadOsd = class {
_startButtonActionEdition(button) {
let ch = String.fromCharCode('A'.charCodeAt() + button);
let key = 'button' + ch;
let key = `button${ch}`;
this._startActionEdition(key, Meta.PadActionType.BUTTON, button);
}

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