Compare commits

...

166 Commits

Author SHA1 Message Date
Georges Basile Stavracas Neto
87a76a5757 appDisplay: Close popup when dragging
When a drag starts inside a folder, and the cursor moves to
outside it, close the currently opened folder popup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:04 -03:00
Georges Basile Stavracas Neto
717ec0f8a4 folderView: Allow moving to specific position
As of now, the only way to add an app icon to a folder is
by dragging it to the folder icon itself. Even though we
allow opening the folder popup when hovering the icon,
dropping an app icon there wouldn't work.

Make the folder view add the app icon to it's GSettings
key (which will trigger _redisplay() and will show the
new icon) when dropping to a specific position.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:03 -03:00
Georges Basile Stavracas Neto
854922866b appIcon: Create and delete folders with DnD
Create a new folder when dropping an icon over another
icon. Try and find a good folder name by looking into
the categories of the applications.

Delete the folder when removing the last icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:03 -03:00
Georges Basile Stavracas Neto
40ad9ab18c appIcon: Show folder preview when dragging over
WIP

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:03 -03:00
Georges Basile Stavracas Neto
55eb949def baseViewIcon: Introduce base class for view icons
Right now, only AppIcon supports being dragged. In the future,
however, both app and folder icons will be reorderable, and to
avoid copying the same code between FolderIcon and AppIcon,
add a new base class BaseViewIcon that contains the shared code
between them.

Adding this new base class also has the side effect that it
already allows for folder icons to be dragged, although full
support for that will come in next commits.

Because the Dash icons are not drop targets themselves, add a
tiny DashIcon class, which is an AppDisplay.AppIcon subclass,
and disable all DND drop code from it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:03 -03:00
Georges Basile Stavracas Neto
0596848c27 appIcon: Use a real BaseIcon as the drag actor
Moving an app icon to other positions is semantically different
to dragging an actor to the dash; the act of moving should itself
be semantic, in that we should feel like we are moving the actual
icon.

Currently, AppIcon gives the DnD code a simplified version of itself,
with just its icon, instead of a complete copy with the label.

Make AppIcon create a new IconGrid.BaseIcon and use it as the drag
actor.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:02 -03:00
Georges Basile Stavracas Neto
0bdcf2958f iconGrid: Apply delay to easing state
Also following design suggestion, add a small delay to the icons
moving so as to give the impression that they're moving in order.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:02 -03:00
Georges Basile Stavracas Neto
ac3bc03f3f iconGrid: Implicitly animate icon positions
Add a proper easing state, and animate icon positions using
Clutter implicit animations.

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:02 -03:00
Georges Basile Stavracas Neto
6e3696baad allView, folderView: Implement moving icons
This makes use of the new BaseAppIcon.moveItem() API.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:01 -03:00
Georges Basile Stavracas Neto
4056c56800 allView: Add support for custom positioning
Use the new 'icon-grid-layout' key to sort the applications and folders
as it is saved. Applications that are not in the key are appended, and
when compared to each other, fallback to alphabetical order.

Because the 'icon-grid-layout' key is, by default, empty, this means that
all icons and folders are sorted alphabetically the first time they are
displayed, preserving the current behavior.

This commit does not add any way to change the order without modifying
the GSettings key directly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:01 -03:00
Georges Basile Stavracas Neto
ebf2610140 folderView: Move DnD functions to BaseAppView
It will be much easier to handle Drag n' Drop with BaseAppView
implementing default handlers for it.

Move handleDragOver() and acceptDrop() to BaseAppView.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:01 -03:00
Georges Basile Stavracas Neto
a9e7b7853a iconGrid: Add item nudge API
Nudging an item can be done via one side, or both. This is
essentially a set of helpers for Drag n' Drop to use. The
x and y values are relative to the icon grid itself.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:00 -03:00
Georges Basile Stavracas Neto
0dd430f2f4 appDisplay: Add moveItem()
This is a handy function to implement changing an icon's position
in the grid.

WIP: better commit message

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:00 -03:00
Georges Basile Stavracas Neto
ca01b0287e allView: Don't sort icons
We are moving towards being able to move icons to custom
positions. To achieve that, the icon grid should stop
sort its icons.

Remove the sorting code from AllView and BaseAppView.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:00 -03:00
Georges Basile Stavracas Neto
37aa5d0faf gschema: Add the 'icons-data' key
This is the key that will store the icons of the icon grid. It is a
sorted array of application ids, and the order of items saved in this
key corresponds to the icon order.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:33:00 -03:00
Georges Basile Stavracas Neto
2e4fb404a7 controlsManager: Don't fade icon grid while dragging
As pointed out by designers, fading it signals that the
icon grid is not a drop target, when now it actually is.

Remove the fade effect applied to the icon grid when
dragging.

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

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

Add an animation to these icons when showing.

WIP: tentatively using the Tweener parameters from Endless OS.

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:32:59 -03:00
Georges Basile Stavracas Neto
241b4cd1c8 allView: Set delegate field
DnD still relies on the _delegate field being set, so
set it.

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:32:58 -03:00
Georges Basile Stavracas Neto
6da23c8d4d appIcon: Always pass parent view
We will soon need to know which view this icon belongs to,
so add an extra parameter to the constructor to store the
parent view.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:32:58 -03:00
Georges Basile Stavracas Neto
bb9f05843f folderIcon: Update folder icon after dropping
After dropping an application into the folder icon, the
list of applications is updated but the folder icon itself
is not.

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

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

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

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/603
2019-08-02 16:32:57 -03:00
Georges Basile Stavracas Neto
038917e5f1 allView: Redisplay on folder changes
Now that redisplaying is a lightweight operation that only
adds and removes what changed, we don't need to just refilter
the app icons in AllView when a folder changes.

Call _redisplay() in AllView when folders change.

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

Remove BaseAppView.addItem().

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

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

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

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

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-02 16:32:56 -03:00
Georges Basile Stavracas Neto
47d2f4dbeb baseAppView: Add only non-added icons, in order
In the close future, BaseAppView will only add new icons (compared
to the remove all + readd all approach that is now). With that, the
items in the this._allItems array will be iterated multiple times,
but items can only be added once, and in the order they're in the
array.

Add the items in the this._allItems array passing the index they
should be added, and don't add icons with a parent already set.

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

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

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

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

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

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

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/645
2019-08-02 16:32:56 -03:00
Georges Basile Stavracas Neto
6c85bd6aeb shell/app-system: Monitor for icon theme changes
Whenever an app is installed, the usual routine is
to run 'gtk-update-icon-cache' after installing all
of the app's files.

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

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
2019-08-02 16:31:54 -03:00
Georges Basile Stavracas Neto
06a7ab871f st/texture-cache: Monitor GtkIconTheme changes
The texture cache, right now, only monitors for
complete theme changes. If the contents of the
icon theme change, however, the texture cache
isn't properly invalidated.

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
2019-08-02 16:31:39 -03:00
Florian Müllner
12b8fb15b1 st: Move slow-down-factor into settings
Now that we have a Settings singleton, we have a better place for the
slow-down-factor than an awkward extern variable.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/656
2019-08-01 21:13:28 +00:00
Florian Müllner
5295866eff st: Fix property type
Commit 8f3554ff accidentally changed the type of the StWidget:track-hover
property from boolean to object.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1482
2019-08-01 12:44:33 +02:00
Florian Müllner
02b47f4640 weather: Fix property name
It's g-*name*-owner. As the condition covers the unlikely case where
Weather is running before gnome-shell, this slipped through.
2019-08-01 01:50:13 +02:00
Marco Trevisan (Treviño)
108ac7cf20 ci: Make eslint wrapper script usable outside gitlab's CI
The eslint wrapper script is useful for development as well, but it currently
fails on systems where bash is not installed in /usr/bin.

Make it useful there as well by changing the shebang to use /usr/bin/env

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/655
2019-07-31 23:28:43 +02:00
Florian Müllner
933c037c6e weather: Stop accessing app settings directly
Our current Weather integration depends on poking around the app's
settings, which we cannot do when the app is sandboxed (as its
filesystem is "hidden away" in a container in that case).

So instead, use our own GSettings schema for the settings, and sync
it with GNOME Weather via a custom D-Bus interface.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1158
2019-07-31 19:04:41 +00:00
Niels De Graef
8f3554ff3e st: Use g_object_notify_by_pspec()
`g_object_notify()` actually takes a global lock to look up the property
by its name, which means there is a performance hit (albeit tiny) every
time this function is called. For this reason, always try to use
`g_object_notify_by_pspec()` instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/652
2019-07-31 17:35:03 +00:00
Marco Trevisan (Treviño)
668128f8c9 lightbox: Remove previously added tweens from target
Since commit 007d30573 we use an actor effect to apply the radial effect and
we pass the effect to the tweener in order to animate it.

However, we always still remove the previously added tween from the actor,
instead that from the actual target.

So, depending the radial effect state, remove the tweens from the proper target

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/653
2019-07-31 19:19:28 +02:00
Niels De Graef
28ab1f4af4 Ensure G_PARAM_STATIC_STRINGS for all properties
In `st`, we can do this by using `ST_PARAM_*`. In the other code files,
just use `G_PARAM_STATIC_STRINGS` directly.

This is just a minor convenience to prevent a few unnecessary string
copies.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/646
2019-07-30 13:58:44 +00:00
Niels De Graef
d360114226 st: Cleanup ST_PARAM_* and add WRITABLE version
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/646
2019-07-30 13:58:44 +00:00
Florian Müllner
5fc456d9d9 userWidget: Handle non-square icons gracefully
We currently assume that user icons are square, which is the case when
set by the users settings panel, but not enforced by AccountsService.

Handle that case by moving the pixel size back to the actor and using
an appropriate background-size style property of 'cover' (which means
the smallest dimension of the image is scaled to fit the desired size).

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1144
2019-07-29 16:16:22 +00:00
Florian Müllner
007d305736 shell: Actually make GLSLEffect an effect
A generic, introspectable Shader effect is not only more flexible
than a shader actor, it will also make it much easier to turn
Lightbox into an actor subclass and replace Tweener with Clutter's
own animation support.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651
2019-07-29 17:51:14 +02:00
Florian Müllner
ae7ec648b2 shell: Properly rename type
This is just a find-and-replace name change to make the actual code
changes in the follow-up commit more apparent.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651
2019-07-29 17:51:14 +02:00
Florian Müllner
99a2fad311 shell: Rename GLSLQuad to GLSLEffect
You can guess where this is going ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651
2019-07-29 17:51:14 +02:00
Florian Müllner
82d466598c lightbox: Remove unnecessary params
Actors have a default origin of (0, 0), so there's no need of
setting those explicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/651
2019-07-29 17:51:14 +02:00
Jonas Dreßler
3a748fe737 theme: Fix focus style of icons in the calendar popup
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1474
2019-07-28 15:43:56 +00:00
Jonas Dreßler
89ce53e3ff shellDBus: Use floats instead of percentages for OSD levels
Due to typecasting being done when converting floats to integers in
gnome-settings-daemon, a volume of 0.9% in g-s-d will end up as 0% in
gnome-shell. This can lead to a mismatch of icons between the volume OSD
(the icon to use is determined by g-s-d itself) and the shells own
volume indicator (the icon to use is determined by the shell using the
volume received from g-s-d).

To fix this, simply get rid of the conversion from float to percentage
in g-s-d and back to floats in the shell and just send a float/double
value on DBus.

https://gitlab.gnome.org/GNOME/gnome-settings-daemon/merge_requests/78
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
verdre
2f29081667 osdWindow: Remove LevelBar and use BarLevel directly
LevelBar is not really used, all the checks are implemented inside
BarLevel as well and the accessible name is wrong because the osdWindow
doesn't only show the volume, but also the brightness and other things.

The workaround for updating the bars width is also no longer needed now
that we have BarLevel.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
verdre
cb0d28770f osdWindow: Use float values as input for osdWindow
Using the same type/interval as BarLevel means we can cut out the intermediate
LevelBar class in a follow-up cleanup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
verdre
86c3909908 barLevel: Return when trying to set value to already used value
There are some cases (for example when tweening value changes), where
the level will be set to the same value it already is at. Avoid those
unnecessary repaints by checking whether the value is already used and
returning if it is.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
Florian Müllner
b970ee7293 barLevel: Use setters instead of methods
Switching to getters/setters make the code suitable for using
with Tweener and as GObject properties, both of which we'll
do soon enough.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
verdre
5545e84430 volume: Remove unused method
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/385
2019-07-28 17:27:53 +02:00
Fabio Tomat
85d9f39417 Update Friulian translation 2019-07-28 07:37:16 +00:00
Jordi Mas
a81450df17 Update Catalan translation 2019-07-28 00:49:20 +02:00
Kukuh Syafaat
a7c94b2cd2 Update Indonesian translation 2019-07-26 11:24:57 +00:00
Florian Müllner
9d65c8b2ec ci: Remove path limitation of js60 check
The check is supposed to run for all merge requests that touch javascript
files, but for some reason I see it's skipped quite often. Better have
the test run unnecessarily some times than let bugs through, so remove
the limitation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/647
2019-07-25 22:37:22 +02:00
Florian Müllner
1b7ff76092 ci: Fix identifying commits in MR
When a MR uses a private namespace, "origin" refers to that, and its
master branch may be outdated with regard to upstream master.

We are really only interested in checking the line changes from the commits
in the MR, so figure out the correct branch point instead.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/647
2019-07-25 22:31:31 +02:00
Bastien Nocera
17e32bf16d docs: Fix interface prefix for D-Bus docs
The --interface-prefix= gtk-doc argument was being passed a stringified
array instead of a simple string.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/644
2019-07-25 15:56:20 +02:00
Asier Sarasua Garmendia
74905f3edc Update Basque translation 2019-07-25 06:43:46 +00:00
Georges Basile Stavracas Neto
8e1b13ca96 appDisplay: Trivial code style improvement
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/643
2019-07-24 18:55:50 -03:00
Georges Basile Stavracas Neto
c0e90807e0 baseIcon: Align labels to the center
Ensure icon labels are aligned to the center, both
vertically and horizontally. This will be required
for using BaseIcons as drag actors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/643
2019-07-24 18:55:50 -03:00
Georges Basile Stavracas Neto
3db1058c2c appIcon: End running drag operations on destroy
AppIcon makes itself draggable, and handles the various DnD
routines such as 'drag-begin' and 'drag-end' by making the
Overview emit the appropriate signals.

However, when destroyed, the AppIcon does not try to finish
any drag operations that started. That causes the event
blocker in AllView not to be updated correctly when dragging
icons to outside folders.

Make AppIcon emit 'item-drag-end' when a drag operation
started and it's destroyed.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/643
2019-07-24 18:11:25 -03:00
Jor Teron
a57c4c580e Update Karbi translation 2019-07-24 18:42:40 +00:00
Daniel Mustieles
33bbbdc322 Updated Spanish translation 2019-07-24 09:51:21 +02:00
Jor Teron
5826336a77 Update Karbi translation 2019-07-24 03:11:21 +00:00
Florian Müllner
3b5d13a0b2 ci: Add eslint job to review stage
We have now reduced the number of eslint errors enough to add it to
the CI pipeline. There are still plenty of errors left though, so we
cannot simply run eslint and fail on any errors. So instead, run it
through a fancy script that:

 - generates an eslint report using the "regular" configuration
 - generates an eslint report using the "legacy" configuration
 - creates a combined report with errors common to both configurations

When the pipeline is running for a branch or tag, the final report is
printed out and the job succeeds (we know there are errors left);
when the pipelne is running for a merge request, we fail if any errors
are reported for the lines modified/added by the MR.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:35:25 +02:00
Florian Müllner
ed37ba1d9b ci: Merge 'source_check' stage into 'review'
GNOME apps use 'review' for the CI stage that generates and exports a
flatpak bundle after a successful build, so they need some other name
for anything that is checked before building; that's how we ended up
with the somewhat awkward 'source_check' stage (inherited from Polari).

But since the commit log check added a 'review' stage that runs pre-build,
use that for all checks that are performed before the build stage.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:34:55 +02:00
Florian Müllner
8ea6fd1925 ci: Include git in extension-ci image
It's useful for anything that does not want to limit itself to the
checked out branch, like comparing source and target branch.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
93a461f3f7 perf: Shut up another eslint error
The functions here are asynchronous to handle control back to the
mainloop while waiting for an action to complete, not to run operations
in parallel. That is, the race condition the rule is protecting against
isn't an issue here, so disable the error.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
fda7c9b06e perf: Shut up an eslint error
The while(true) loop is intentional here and not a bug, so disable
the corresponding eslint rule.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
1e13f32cea style: Disable camelcase rule for GObject properties
For GObject properties, we follow the convention of all-lowercase,
dash-separated names. Those translate to underscores in getters/setters,
so exempt them from the newly added "camelcase" rule.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
e357559582 cleanup: Mark globals used from other modules as exported
eslint cannot figure out that those symbols are used from other modules
via imports, so they trigger unused-variable errors. To fix, explicitly
mark those symbols as exported.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
71759a0769 cleanup: Mark unused (but useful) variables as ignored
While we aren't using those destructured variables, they are still useful
to document the meaning of those elements. We don't want eslint to keep
warning about them though, so mark them accordingly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
11b116cb9d cleanup: Remove some unhelpful unused variables in destructuring
We aren't using them, and they don't add much in terms of clarity,
so drop them to fix a couple of eslint errors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
2f97a1a55d cleanup: Mark unused arguments as unused
This will stop eslint from warning about them, while keeping their
self-documenting benefit.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
79cf3a6dd0 cleanup: Remove some unhelpful unused arguments
Those unused arguments aren't bugs - unbeknownst to eslint, they all
correspond to valid signal parameters - but they don't contribute
anything to clarity, so just remove them anyway.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
0257de1b7e lint: Allow marking variables/arguments as unused
Unused variables or arguments can indicate bugs, but they can also
help document the code, in particular in case of signal handlers
and destructuring.

Account for this by keeping the error, but set up patterns that allow
us to opt out of if for individual variables/arguments. For arguments
we pick a '_' prefix, while for variables we go with a suffix instead,
to not accidentally exempt private module-scope variables.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/627
2019-07-24 00:28:45 +02:00
Florian Müllner
466dc8da8f build: Automatically bump mutter API version each cycle
Mutter will now bump the API version automatically at the
beginning of a new development cycle; do the same here.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/641
2019-07-23 21:57:21 +00:00
Kristjan SCHMIDT
2c61badc02 Update Esperanto translation 2019-07-23 19:08:49 +00:00
Florian Müllner
3f8d3a7ee2 panel: Remove unused constant
This was left-over in commit 2743f18af, and probably is the real reason
why the busy spinner wasn't using the shared AnimatedIcon.Spinner class:
The animation there was much slower.

Still, let's keep the code as-is for now, if we really need a different
animation time, we can add an optional constructor parameter to the
Spinner class.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/640
2019-07-23 20:05:19 +02:00
Florian Müllner
a455860978 appDisplay: Indent with spaces rather than tabs
Another style nit that sneaked in with commit eaa32090b9.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/640
2019-07-23 20:05:19 +02:00
Florian Müllner
0ecf135a4b appDisplay: Add missing semicolon
This slipped through in commit eaa320 ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/640
2019-07-23 20:05:19 +02:00
Ray Strode
cebb6d40df appDisplay: Keep popup open on refresh
If the list of applications is refreshed we currently close
the open app folder.

This commit adds logic to reopen the app folder on reload.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
0ee13672ee appDisplay: Add open method to FolderIcon
At the moment the only way to open a folder icon is to click on it;
there's no API to open the icon programmatically.

This commits adds an open method and makes the click handler use
it.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
49260a85ad appDisplay: Stop watching FolderIcon parent view when destroyed
When a FolderIcon is opened, it asks the parent view to allocate
space for it, which takes time.  Eventually, the space-ready
signal is emitted on the view and the icon can make use of the new
space with its popup.  If the icon gets destroyed in the
interim, though, space-ready signal handler still fires.

This commit disconnects the signal handler so it doesn't get called
on a destroyed icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
da9f37e629 appDisplay: Add destroy handler for FolderIcon
It is important that the FolderView of a FolderIcon always
gets destroyed before the AppFolderPopup, since the view
may or may not be in the popup, and the view should
get cleaned up exactly once in either case.

This commit adds a destroy handler on FolderIcon to ensure
things get taken down in the right order, and to make sure
the view isn't leaked if it's not yet part of the popup.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
164f3fa3fd appDisplay: Clear AllView reference to current popup when destroyed
AllView contains a reference to the current popup that lingers after
the popup is destroyed.

This commit fixes that, by explicitly nullifying when appropriate.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
8e75d81a44 appDisplay: Add AppFolderPopup destroy handler
At the moment AppFolderPopup calls popdown on destruction,
which leads to open-state-changed getting emitted after
the actor associated with the popup is destroyed.

This commit handles ungrabbing and closing from an
actor destroy handler to side-step the open-state-changed
signal.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
1d60c4d9d4 iconGrid: Clear meta_later callback on destruction
The IconGrid code sometimes sets up a callback to be invoked
later right before being destroyed.

This commit adds a destroy handler to cancel the callback.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Ray Strode
eaa32090b9 appDisplay: Don't leak duplicate items in AppView
If an icon already exists in an app view with the same id, the
duplicate is not added on a call to addItem.  Unfortunately,
since it's not added, the icon actor gets orphaned and leaked.

This commit address the problem by introducing a new hasItem
method and disallowing callers to call addItem with a duplicate
in the first place.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/628
2019-07-23 14:53:24 +00:00
Daniel van Vugt
32ddb6f739 iconGrid: Add missing import for GLib
To silence warnings:

JS ERROR: ReferenceError: GLib is not defined
_updateIconSizes@resource:///org/gnome/shell/ui/iconGrid.js:771:9

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1462
2019-07-23 09:29:56 +00:00
Florian Müllner
2653402c5c js: Add missing return values to later_add() handlers
meta_later_add() is modelled after g_idle_add() and friends, and
the handler's boolean return value determines whether it should
be scheduled again or removed. There are some places where we omit
the return value, add them (although the implicit return value of
"undefined" already gives us the intended result).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/637
2019-07-22 20:48:16 +02:00
Florian Müllner
2743f18af4 panel: Use dedicated Spinner class
The startup/busy indication in the app menu was left out of commit
22e21ad7d1 because it doesn't use a hard-coded image, but as the
image in the CSS is actually the same used by the spinner class,
drop the "custom" styling and use the regular spinner.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/636
2019-07-22 17:50:52 +02:00
Florian Müllner
dd1fdf88ff extensionPrefs: Add missing return value
When commit a7ec7583aa merged two functions into one, it left
out the expected return value from one branch.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/635
2019-07-22 13:18:55 +00:00
Florian Müllner
2a041e9d8d lint: Enforce consistent return
While all javascript functions have a return value - either an explicit
one from a return statement, or an implicit "undefined" - mixing both in
the same function is almost certainly an oversight, and more often than
not a bug.

Enable the corresponding eslint rule to catch those errors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/635
2019-07-22 13:18:55 +00:00
Rafael Fontenelle
1117f4760c Update Brazilian Portuguese translation 2019-07-22 02:49:59 +00:00
Asier Sarasua Garmendia
7dda7abf5e Update Basque translation 2019-07-21 18:27:36 +00:00
Florian Müllner
7ca3cca306 build: Bump gsettings-desktop-schemas requirement
... for the new disable-hot-corners setting.
2019-07-20 18:25:29 +02:00
Florian Müllner
d471e3a23b Bump version to 3.33.4
Update NEWS.
2019-07-20 17:47:10 +02:00
Didier Roche
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
Florian Müllner
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
Florian Müllner
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
Didier Roche
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
Florian Müllner
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
Didier Roche
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
Didier Roche
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
Florian Müllner
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
Didier Roche
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
Didier Roche
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
2768b73015 build: Clean out unused version requirements
We haven't linked to those libraries in years ...
2019-07-20 12:39:16 +02:00
Florian Müllner
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
Ting-Wei Lan
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Jakub Steiner
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
Marco Trevisan (Treviño)
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
Jakub Steiner
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
Jakub Steiner
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
Jakub Steiner
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
Jor Teron
f583a7c6d8 Update Karbi translation 2019-07-16 02:39:07 +00:00
Jonas Dreßler
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
Jonas Dreßler
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
Jonas Dreßler
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
Jonas Dreßler
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
Jonas Dreßler
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
Jor Teron
a823a213ba Update Karbi translation 2019-07-15 10:54:50 +00:00
Benjamin Berg
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
Jor Teron
3996309f8a Add Karbi translation 2019-07-14 04:02:53 +00:00
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
1570f838f3 cleanup: Remove bogus file
This was accidentally added in commit 14d7897a9.
2019-07-12 10:36:37 +00:00
Florian Müllner
74feb110b5 layout: Fix off-by-one indent
This sneaked into commit dbb71f0d :-(
2019-07-11 03:02:20 +02:00
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Florian Müllner
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
Illya Klymov
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
Florian Müllner
5473637736 cleanup: Fix style nits in last commit
Missing space after catch and wrong double quotes.
2019-07-08 20:15:15 +02:00
188 changed files with 9460 additions and 4737 deletions

6
.eslintrc.json Normal file
View File

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

View File

@@ -1,6 +1,5 @@
stages:
- review
- source_check
- build
- test
@@ -26,19 +25,27 @@ check_commit_log:
js_check:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: source_check
stage: review
script:
- find js -name '*.js' -exec js60 -c -s '{}' ';' 2>&1 | tee $JS_LOG
- (! grep -q . $JS_LOG)
<<: *only_default
only:
changes:
- js/**/*
artifacts:
paths:
- ${JS_LOG}
when: on_failure
eslint:
image: registry.gitlab.gnome.org/gnome/gnome-shell/extension-ci:v1
stage: review
script:
- ./.gitlab-ci/run-eslint.sh
<<: *only_default
artifacts:
paths:
- reports
when: always
build:
image: registry.gitlab.gnome.org/gnome/mutter/master:v2
stage: build

View File

@@ -1,7 +1,7 @@
FROM registry.fedoraproject.org/fedora:latest
RUN dnf -y update && dnf -y upgrade && \
dnf install -y 'dnf-command(copr)' && \
dnf install -y 'dnf-command(copr)' git && \
# For syntax checks with `find . -name '*.js' -exec js60 -c -s '{}' ';'`
dnf install -y findutils mozjs60-devel && \

97
.gitlab-ci/run-eslint.sh Executable file
View File

@@ -0,0 +1,97 @@
#!/usr/bin/env bash
OUTPUT_REGULAR=reports/lint-regular-report.txt
OUTPUT_LEGACY=reports/lint-legacy-report.txt
OUTPUT_FINAL=reports/lint-common-report.txt
OUTPUT_MR=reports/lint-mr-report.txt
LINE_CHANGES=changed-lines.txt
is_empty() {
(! grep -q . $1)
}
run_eslint() {
ARGS_LEGACY='--config lint/eslintrc-legacy.json'
local extra_args=ARGS_$1
local output=OUTPUT_$1
eslint -f unix ${!extra_args} -o ${!output} js
}
list_commit_range_additions() {
# Turn raw context-less git-diff into a list of
# filename:lineno pairs of new (+) lines
git diff -U0 "$@" -- js |
awk '
BEGIN { file=""; }
/^+++ b/ { file=substr($0,7); }
/^@@ / {
len = split($3,a,",")
start=a[1]
count=(len > 1) ? a[2] : 1
for (line=start; line<start+count; line++)
printf "%s/%s:%d:\n",ENVIRON["PWD"],file,line;
}'
}
copy_matched_lines() {
local source=$1
local matches=$2
local target=$3
echo -n > $target
for l in $(<$matches); do
grep $l $source >> $target
done
}
create_common() {
# comm requires sorted input;
# we also strip the error message to make the following a "common" error:
# regular:
# file.js:42:23 Indentation of 55, expected 42
# legacy:
# file.js:42:23 Indentation of 55, extected 24
prepare() {
sed 's: .*::' $1 | sort
}
comm -12 <(prepare $OUTPUT_REGULAR) <(prepare $OUTPUT_LEGACY) >$OUTPUT_FINAL.tmp
# Now add back the stripped error messages
copy_matched_lines $OUTPUT_REGULAR $OUTPUT_FINAL.tmp $OUTPUT_FINAL
rm $OUTPUT_FINAL.tmp
}
if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
git fetch $CI_MERGE_REQUEST_PROJECT_URL.git $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
branch_point=$(git merge-base HEAD FETCH_HEAD)
commit_range=$branch_point...$CI_COMMIT_SHA
list_commit_range_additions $commit_range > $LINE_CHANGES
# Don't bother with running lint when no JS changed
if is_empty $LINE_CHANGES; then
exit 0
fi
fi
echo Generating lint report using regular configuration
run_eslint REGULAR
echo Generating lint report using legacy configuration
run_eslint LEGACY
echo Done.
create_common
# Just show the report and succeed when not testing a MR
if [ -z "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
cat $OUTPUT_FINAL
exit 0
fi
copy_matched_lines $OUTPUT_FINAL $LINE_CHANGES $OUTPUT_MR
cat $OUTPUT_MR
is_empty $OUTPUT_MR

26
NEWS
View File

@@ -1,3 +1,29 @@
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]

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

@@ -0,0 +1,16 @@
<node>
<!--
org.gnome.Shell.WeatherIntegration:
@short_description: Weather integration interface
The interface used for exporting location settings to GNOME Shell's
weather integration.
-->
<interface name="org.gnome.Shell.WeatherIntegration">
<property name="AutomaticLocation" type="b" access="read"/>
<property name="Locations" type="av" access="read"/>
</interface>
</node>

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

@@ -48,6 +48,7 @@
<file preprocess="xml-stripblanks">org.gnome.Shell.Screencast.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Screenshot.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.Wacom.PadOsd.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.WeatherIntegration.xml</file>
<file preprocess="xml-stripblanks">org.gnome.Shell.xml</file>
<file preprocess="xml-stripblanks">org.Gtk.MountOperationHandler.xml</file>
<file preprocess="xml-stripblanks">org.gtk.Notifications.xml</file>

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>
@@ -98,6 +109,10 @@
the shell.
</description>
</key>
<key name="icons-data" type="a{sv}">
<default>[]</default>
<summary>Data about the icons in the icon grid</summary>
</key>
<child name="keybindings" schema="org.gnome.shell.keybindings"/>
</schema>
@@ -222,6 +237,25 @@
</key>
</schema>
<schema id="org.gnome.shell.weather" path="/org/gnome/shell/weather/"
gettext-domain="@GETTEXT_PACKAGE@">
<key name="automatic-location" type="b">
<summary>Automatic location</summary>
<description>
Whether to fetch the current location or not
</description>
<default>false</default>
</key>
<key name="locations" type="av">
<summary>Location</summary>
<description>
The location for which to show a forecast
</description>
<default>[]</default>
</key>
</schema>
<!-- unused, change 00_org.gnome.shell.gschema.override instead -->
<schema id="org.gnome.shell.overrides" path="/org/gnome/shell/overrides/"
gettext-domain="@GETTEXT_PACKAGE@">

View File

@@ -619,6 +619,18 @@ StScrollBar {
app menu inside the main app window itself rather than the top bar
*/
/*************
* App Icons *
*************/
/* Outline for low res icons */
.lowres-icon {
icon-shadow: 0 1px 2px rgba(0,0,0,0.3);
}
/* Drapshadow for large icons */
.icon-dropshadow {
icon-shadow: 0 1px 2px rgba(0,0,0,0.4);
}
/* OSD */
.osd-window {
@@ -728,7 +740,8 @@ StScrollBar {
spacing: 8px;
}
.ws-switcher-active-up, .ws-switcher-active-down {
.ws-switcher-active-up, .ws-switcher-active-down,
.ws-switcher-active-left, .ws-switcher-active-right {
height: 50px;
background-color: $selected_bg_color;
color: $selected_fg_color;
@@ -929,7 +942,7 @@ StScrollBar {
.world-clocks-button,
.weather-button,
.events-section-title {
&:hover, focus { background-color: $_hover_bg_color }
&:hover, &:focus { background-color: $_hover_bg_color }
&:active { background-color: $_active_bg_color }
}
@@ -1000,7 +1013,7 @@ StScrollBar {
background-color: transparent;
width: 32px;
border-radius: 4px;
&:hover, focus { background-color: $_hover_bg_color; }
&:hover, &:focus { background-color: $_hover_bg_color; }
&:active { background-color: transparentize($fg_color, 0.84); }
}
@@ -1016,7 +1029,7 @@ StScrollBar {
margin: 2px;
border-radius: 1.4em;
font-feature-settings: "tnum";
&:hover, focus { background-color: $_hover_bg_color; }
&:hover, &:focus { background-color: $_hover_bg_color; }
&:active,&:selected {
color: lighten($selected_fg_color,5%);
background-color: $selected_bg_color;
@@ -1158,7 +1171,6 @@ StScrollBar {
// a little unstructured mess:
#appMenu {
spinner-image: url("resource:///org/gnome/shell/theme/process-working.svg");
spacing: 4px;
.label-shadow { color: transparent; }
@@ -1326,8 +1338,8 @@ StScrollBar {
.window-clone-border {
$_bg: transparentize(white, 0.65);
border: 5px solid $_bg;
border-radius: 6px;
border: 7px solid $_bg;
border-radius: $modal_radius;
// For window decorations with round corners we can't match
// the exact shape when the window is scaled. So apply a shadow
// to fix that case
@@ -1364,11 +1376,8 @@ StScrollBar {
//search results
#searchResultsBin {
max-width: 1000px;
}
#searchResultsContent {
max-width: 1000px;
padding-left: 20px;
padding-right: 20px;
spacing: 16px;
@@ -1484,11 +1493,11 @@ StScrollBar {
.search-provider-icon,
.list-search-result {
@extend %icon_tile;
&:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); }
&:focus, &:selected, &:hover {
background-color: transparentize($osd_fg_color,.9);
transition-duration: 200ms;
}
&:active, &:checked { background-color: transparentize(darken($osd_bg_color,10%),.1); }
}
.app-well-app,
.app-well-app.app-folder,
@@ -1497,10 +1506,6 @@ StScrollBar {
& .overview-icon {
@extend %icon_tile;
}
&:active .overview-icon,
&:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5);
}
&:hover .overview-icon,
&:focus .overview-icon,
&:selected .overview-icon {
@@ -1509,7 +1514,13 @@ StScrollBar {
border-image: none;
background-image: none;
}
&:drop .overview-icon {
background-color: transparentize($selected_bg_color,.15);
}
&:active .overview-icon,
&:checked .overview-icon {
background-color: transparentize(darken($osd_bg_color,10%), 0.5);
}
}
.app-well-app-running-dot { //running apps indicator
@@ -1599,7 +1610,6 @@ StScrollBar {
}
//Some hacks I don't even
.search-display > StBoxLayout,
.all-apps,
.frequent-apps > StBoxLayout {
// horizontal padding to make sure scrollbars or dash don't overlap content

View File

@@ -28,7 +28,7 @@ foreach iface : ifaces
output: 'doc-gen-' + iface[1],
command: [
'gdbus-codegen',
'--interface-prefix=@0@.'.format(iface),
'--interface-prefix=@0@.'.format(iface[0]),
'--generate-docbook', 'doc-gen',
'--output-directory', '@OUTDIR@',
'@INPUT@'

View File

@@ -1,3 +1,4 @@
/* exported main */
const Gettext = imports.gettext;
const { Gdk, GLib, Gio, GObject, Gtk, Pango } = imports.gi;
const Format = imports.format;
@@ -8,6 +9,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 +20,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;
@@ -96,9 +79,11 @@ var Application = class {
dialog.set_default_size(600, 400);
dialog.add(widget);
dialog.show();
return true;
}
_buildErrorUI(extension, exc) {
_buildErrorUI(row, exc) {
let scroll = new Gtk.ScrolledWindow({
hscrollbar_policy: Gtk.PolicyType.NEVER,
propagate_natural_height: true
@@ -170,7 +155,7 @@ var Application = class {
let clipboard = Gtk.Clipboard.get_default(w.get_display());
// markdown for pasting in gitlab issues
let lines = [
`The settings of extension ${extension.uuid} had an error:`,
`The settings of extension ${row.uuid} had an error:`,
'```',
`${exc}`,
'```',
@@ -192,13 +177,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({
@@ -213,8 +198,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);
@@ -248,18 +233,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) {
@@ -270,19 +251,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();
@@ -295,24 +312,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) {
@@ -323,16 +342,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: {
@@ -499,6 +516,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) {
@@ -511,30 +557,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 });
@@ -544,19 +615,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,
@@ -566,51 +638,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.includes(this.uuid);
}
get prefsModule() {
if (!this._prefsModule) {
ExtensionUtils.installImporter(this._extension);
_enable() {
let extensions = this._settings.get_strv('enabled-extensions');
if (extensions.includes(this.uuid))
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;
}
});
@@ -638,6 +696,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

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported FprintManager */
const Gio = imports.gi.Gio;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LoginDialog */
/*
* Copyright 2011 Red Hat, Inc
*
@@ -372,7 +373,7 @@ var SessionMenuButton = class {
}
for (let i = 0; i < ids.length; i++) {
let [sessionName, sessionDescription] = Gdm.get_session_name_and_description(ids[i]);
let [sessionName, sessionDescription_] = Gdm.get_session_name_and_description(ids[i]);
let id = ids[i];
let item = new PopupMenu.PopupMenuItem(sessionName);
@@ -518,7 +519,7 @@ var LoginDialog = GObject.registerClass({
_getBannerAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = this._bannerView.get_preferred_size();
let [, , natWidth, natHeight] = this._bannerView.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -532,7 +533,7 @@ var LoginDialog = GObject.registerClass({
_getLogoBinAllocation(dialogBox) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = this._logoBin.get_preferred_size();
let [, , natWidth, natHeight] = this._logoBin.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
actorBox.x1 = Math.floor(centerX - natWidth / 2);
@@ -546,7 +547,7 @@ var LoginDialog = GObject.registerClass({
_getCenterActorAllocation(dialogBox, actor) {
let actorBox = new Clutter.ActorBox();
let [minWidth, minHeight, natWidth, natHeight] = actor.get_preferred_size();
let [, , natWidth, natHeight] = actor.get_preferred_size();
let centerX = dialogBox.x1 + (dialogBox.x2 - dialogBox.x1) / 2;
let centerY = dialogBox.y1 + (dialogBox.y2 - dialogBox.y1) / 2;
@@ -648,7 +649,7 @@ var LoginDialog = GObject.registerClass({
// 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 [, wideBannerHeight] = this._bannerView.get_preferred_height(wideBannerWidth);
let maxWideHeight = dialogHeight - 3 * logoHeight;
wideBannerHeight = Math.min(maxWideHeight, wideBannerHeight);
@@ -1241,7 +1242,7 @@ var LoginDialog = GObject.registerClass({
this._authPrompt.cancel();
}
addCharacter(unichar) {
addCharacter(_unichar) {
// Don't allow type ahead at the login screen
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getOVirtCredentialsManager */
const Gio = imports.gi.Gio;
const Signals = imports.signals;

View File

@@ -15,7 +15,7 @@ const RealmIface = loadInterfaceXML("org.freedesktop.realmd.Realm");
const Realm = Gio.DBusProxy.makeProxyWrapper(RealmIface);
var Manager = class {
constructor(parentActor) {
constructor() {
this._aggregateProvider = Provider(Gio.DBus.system,
'org.freedesktop.realmd',
'/org/freedesktop/realmd',

View File

@@ -1,4 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY,
DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */
const { Clutter, Gio, GLib } = imports.gi;
const Signals = imports.signals;
@@ -45,7 +47,7 @@ function fadeInActor(actor) {
let hold = new Batch.Hold();
actor.show();
let [minHeight, naturalHeight] = actor.get_preferred_height(-1);
let [, naturalHeight] = actor.get_preferred_height(-1);
actor.opacity = 0;
actor.set_height(0);
@@ -303,7 +305,7 @@ var ShellUserVerifier = class {
});
}
_oVirtUserAuthenticated(token) {
_oVirtUserAuthenticated(_token) {
this._preemptingService = OVIRT_SERVICE_NAME;
this.emit('ovirt-user-authenticated');
}

View File

@@ -1,23 +1,37 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ExtensionState, ExtensionType, getCurrentExtension,
getSettings, initTranslations, isOutOfDate, installImporter,
serializeExtension, deserializeExtension */
// 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:
@@ -49,13 +63,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,52 +179,50 @@ function isOutOfDate(extension) {
return false;
}
function createExtensionObject(uuid, dir, type) {
let metadataFile = dir.get_child('metadata.json');
if (!metadataFile.query_exists(null)) {
throw new Error('Missing metadata.json');
}
function serializeExtension(extension) {
let obj = {};
Lang.copyProperties(extension.metadata, obj);
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}`);
}
SERIALIZED_PROPERTIES.forEach(prop => {
obj[prop] = extension[prop];
});
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) {
@@ -217,36 +233,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

@@ -1,4 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported collectFromDatadirs, deleteGFile, recursivelyDeleteDir,
recursivelyMoveDir, loadInterfaceXML */
const { Gio, GLib } = imports.gi;
const Config = imports.misc.config;
@@ -84,7 +86,7 @@ function loadInterfaceXML(iface) {
let f = Gio.File.new_for_uri(uri);
try {
let [ok, bytes] = f.load_contents(null);
let [ok_, bytes] = f.load_contents(null);
if (bytes instanceof Uint8Array)
xml = imports.byteArray.toString(bytes);
else

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PresenceStatus, Presence, Inhibitor, SessionManager */
const Gio = imports.gi.Gio;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */
const { Clutter, GLib, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
@@ -84,15 +85,15 @@ class InputMethod extends Clutter.InputMethod {
this.emit('request-surrounding');
}
_onCommitText(context, text) {
_onCommitText(_context, text) {
this.commit(text.get_text());
}
_onDeleteSurroundingText(context) {
_onDeleteSurroundingText() {
this.delete_surrounding();
}
_onUpdatePreeditText(context, text, pos, visible) {
_onUpdatePreeditText(_context, text, pos, visible) {
if (text == null)
return;
@@ -108,17 +109,17 @@ class InputMethod extends Clutter.InputMethod {
this._preeditVisible = visible;
}
_onShowPreeditText(context) {
_onShowPreeditText() {
this._preeditVisible = true;
this.set_preedit_text(this._preeditStr, this._preeditPos);
}
_onHidePreeditText(context) {
_onHidePreeditText() {
this.set_preedit_text(null, this._preeditPos);
this._preeditVisible = false;
}
_onForwardKeyEvent(context, keyval, keycode, state) {
_onForwardKeyEvent(_context, keyval, keycode, state) {
let press = (state & IBus.ModifierType.RELEASE_MASK) == 0;
state &= ~(IBus.ModifierType.RELEASE_MASK);

View File

@@ -1,3 +1,4 @@
/* exported IntrospectService */
const { Gio, GLib, Meta, Shell } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell';

View File

@@ -1,4 +1,5 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported getCompletions, getCommonPrefix, getDeclaredConstants */
// Returns a list of potential completions for text. Completions either
// follow a dot (e.g. foo.ba -> bar) or they are picked from globalCompletionList (e.g. fo -> foo)
@@ -8,7 +9,7 @@
// This function is likely the one you want to call from external modules
function getCompletions(text, commandHeader, globalCompletionList) {
let methods = [];
let expr, base;
let expr_, base;
let attrHead = '';
if (globalCompletionList == null) {
globalCompletionList = [];
@@ -21,7 +22,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// Look for expressions like "Main.panel.foo" and match Main.panel and foo
let matches = text.match(/(.*)\.(.*)/);
if (matches) {
[expr, base, attrHead] = matches;
[expr_, base, attrHead] = matches;
methods = getPropertyNamesFromExpression(base, commandHeader).filter(
attr => attr.slice(0, attrHead.length) == attrHead
@@ -32,7 +33,7 @@ function getCompletions(text, commandHeader, globalCompletionList) {
// not proceeded by a dot and match them against global constants
matches = text.match(/^(\w*)$/);
if (text == '' || matches) {
[expr, attrHead] = matches;
[expr_, attrHead] = matches;
methods = globalCompletionList.filter(
attr => attr.slice(0, attrHead.length) == attrHead
);
@@ -151,11 +152,7 @@ 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 {
@@ -234,10 +231,10 @@ function isUnsafeExpression(str) {
function getDeclaredConstants(str) {
let ret = [];
str.split(';').forEach(s => {
let base, keyword;
let base_, keyword;
let match = s.match(/const\s+(\w+)\s*=/);
if (match) {
[base, keyword] = match;
[base_, keyword] = match;
ret.push(keyword);
}
});

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getKeyboardManager, holdKeyboard, releaseKeyboard */
const { GLib, GnomeDesktop, Meta } = imports.gi;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported canLock, getLoginManager, registerSessionWithGDM */
const { GLib, Gio } = imports.gi;
const Signals = imports.signals;
@@ -109,7 +110,7 @@ var LoginManagerSystemd = class {
let sessionId = GLib.getenv('XDG_SESSION_ID');
if (!sessionId) {
log('Unset XDG_SESSION_ID, getCurrentSessionProxy() called outside a user session. Asking logind directly.');
let [session, objectPath] = this._userProxy.Display;
let [session, objectPath_] = this._userProxy.Display;
if (session) {
log(`Will monitor session ${session}`);
sessionId = session;
@@ -182,7 +183,7 @@ var LoginManagerSystemd = class {
(proxy, result) => {
let fd = -1;
try {
let [outVariant, fdList] = proxy.call_with_unix_fd_list_finish(result);
let [outVariant_, fdList] = proxy.call_with_unix_fd_list_finish(result);
fd = fdList.steal_fds()[0];
callback(new Gio.UnixInputStream({ fd: fd }));
} catch (e) {
@@ -199,7 +200,7 @@ var LoginManagerSystemd = class {
Signals.addSignalMethods(LoginManagerSystemd.prototype);
var LoginManagerDummy = class {
getCurrentSessionProxy(callback) {
getCurrentSessionProxy(_callback) {
// we could return a DummySession object that fakes whatever callers
// expect (at the time of writing: connect() and connectSignal()
// methods), but just never calling the callback should be safer

View File

@@ -110,7 +110,7 @@ var ModemGsm = class {
this.signal_quality = quality;
this.emit('notify::signal-quality');
});
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [status, code, name]) => {
this._proxy.connectSignal('RegistrationInfo', (proxy, sender, [_status, code, name]) => {
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
@@ -120,7 +120,7 @@ var ModemGsm = class {
return;
}
let [status, code, name] = result;
let [status_, code, name] = result;
this.operator_name = _findProviderForMccMnc(name, code);
this.emit('notify::operator-name');
});
@@ -171,7 +171,7 @@ var ModemCdma = class {
// it will return an error if the device is not connected
this.operator_name = null;
} else {
let [bandClass, band, sid] = result;
let [bandClass_, band_, sid] = result;
this.operator_name = _findProviderForSid(sid);
}
@@ -224,7 +224,7 @@ var BroadbandModem = class {
}
_reloadSignalQuality() {
let [quality, recent] = this._proxy.SignalQuality;
let [quality, recent_] = this._proxy.SignalQuality;
this.signal_quality = quality;
this.emit('notify::signal-quality');
}

View File

@@ -1,6 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const Lang = imports.lang;
/* exported parse */
// parse:
// @params: caller-provided parameter object, or %null
@@ -23,7 +22,6 @@ function parse(params = {}, defaults, allowExtras) {
throw new Error(`Unrecognized parameter "${prop}"`);
}
let defaultsCopy = {};
Lang.copyProperties(defaults, defaultsCopy);
let defaultsCopy = Object.assign({}, defaults);
return Object.assign(defaultsCopy, params);
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PermissionStore */
const Gio = imports.gi.Gio;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getSmartcardManager */
const Gio = imports.gi.Gio;
const Signals = imports.signals;

View File

@@ -1,3 +1,4 @@
/* exported getDefault */
const { AccountsService, Clutter, Gdm, Gio, GLib, GObject, Meta } = imports.gi;
const GnomeSession = imports.misc.gnomeSession;
@@ -187,30 +188,37 @@ const SystemActions = GObject.registerClass({
this._sessionUpdated();
}
// eslint-disable-next-line camelcase
get can_power_off() {
return this._actions.get(POWER_OFF_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_suspend() {
return this._actions.get(SUSPEND_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_lock_screen() {
return this._actions.get(LOCK_SCREEN_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_switch_user() {
return this._actions.get(SWITCH_USER_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_logout() {
return this._actions.get(LOGOUT_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get can_lock_orientation() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).available;
}
// eslint-disable-next-line camelcase
get orientation_lock_icon() {
return this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName;
}

View File

@@ -1,4 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported findUrls, spawn, spawnCommandLine, spawnApp, trySpawnCommandLine,
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Gettext = imports.gettext;
@@ -75,7 +78,7 @@ function spawn(argv) {
// occur when trying to parse or start the program.
function spawnCommandLine(commandLine) {
try {
let [success, argv] = GLib.shell_parse_argv(commandLine);
let [success_, argv] = GLib.shell_parse_argv(commandLine);
trySpawn(argv);
} catch (err) {
_handleSpawnError(commandLine, err);
@@ -104,11 +107,11 @@ function spawnApp(argv) {
// Runs @argv in the background. If launching @argv fails,
// this will throw an error.
function trySpawn(argv) {
var success, pid;
var success_, pid;
try {
[success, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
[success_, pid] = GLib.spawn_async(null, argv, null,
GLib.SpawnFlags.SEARCH_PATH | GLib.SpawnFlags.DO_NOT_REAP_CHILD,
null);
} catch (err) {
/* Rewrite the error in case of ENOENT */
if (err.matches(GLib.SpawnError, GLib.SpawnError.NOENT)) {
@@ -139,10 +142,10 @@ function trySpawn(argv) {
// Runs @commandLine in the background. If launching @commandLine
// fails, this will throw an error.
function trySpawnCommandLine(commandLine) {
let success, argv;
let success_, argv;
try {
[success, argv] = GLib.shell_parse_argv(commandLine);
[success_, argv] = GLib.shell_parse_argv(commandLine);
} catch (err) {
// Replace "Error invoking GLib.shell_parse_argv: " with
// something nicer
@@ -395,7 +398,7 @@ function makeCloseButton(boxpointer) {
function ensureActorVisibleInScrollView(scrollView, actor) {
let adjustment = scrollView.vscroll.adjustment;
let [value, lower, upper, stepIncrement, pageIncrement, pageSize] = adjustment.get_values();
let [value, lower_, upper, stepIncrement_, pageIncrement_, pageSize] = adjustment.get_values();
let offset = 0;
let vfade = scrollView.get_effect("fade");

View File

@@ -1,10 +1,19 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { Geoclue, Gio, GLib, GWeather } = imports.gi;
const { Geoclue, Gio, GLib, GWeather, Shell } = imports.gi;
const Signals = imports.signals;
const PermissionStore = imports.misc.permissionStore;
const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
const WeatherIntegrationIface = loadInterfaceXML('org.gnome.Shell.WeatherIntegration');
const WEATHER_BUS_NAME = 'org.gnome.Weather';
const WEATHER_OBJECT_PATH = '/org/gnome/Weather';
const WEATHER_INTEGRATION_IFACE = 'org.gnome.Shell.WeatherIntegration';
const WEATHER_APP_ID = 'org.gnome.Weather.desktop';
// Minimum time between updates to show loading indication
var UPDATE_THRESHOLD = 10 * GLib.TIME_SPAN_MINUTE;
@@ -66,17 +75,36 @@ var WeatherClient = class {
this.emit('changed');
});
this._weatherAppMon = new Util.AppSettingsMonitor('org.gnome.Weather.desktop',
'org.gnome.Weather');
this._weatherAppMon.connect('available-changed', () => this.emit('changed'));
this._weatherAppMon.watchSetting('automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._weatherAppMon.watchSetting('locations',
this._onLocationsChanged.bind(this));
this._weatherApp = null;
this._weatherProxy = null;
let nodeInfo = Gio.DBusNodeInfo.new_for_xml(WeatherIntegrationIface);
Gio.DBusProxy.new(
Gio.DBus.session,
Gio.DBusProxyFlags.DO_NOT_AUTO_START | Gio.DBusProxyFlags.GET_INVALIDATED_PROPERTIES,
nodeInfo.lookup_interface(WEATHER_INTEGRATION_IFACE),
WEATHER_BUS_NAME,
WEATHER_OBJECT_PATH,
WEATHER_INTEGRATION_IFACE,
null,
this._onWeatherProxyReady.bind(this));
this._settings = new Gio.Settings({
schema_id: 'org.gnome.shell.weather'
});
this._settings.connect('changed::automatic-location',
this._onAutomaticLocationChanged.bind(this));
this._settings.connect('changed::locations',
this._onLocationsChanged.bind(this));
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('installed-changed',
this._onInstalledChanged.bind(this));
this._onInstalledChanged();
}
get available() {
return this._weatherAppMon.available;
return this._weatherApp != null;
}
get loading() {
@@ -92,7 +120,8 @@ var WeatherClient = class {
}
activateApp() {
this._weatherAppMon.activateApp();
if (this._weatherApp)
this._weatherApp.activate();
}
update() {
@@ -114,6 +143,37 @@ var WeatherClient = class {
this._weatherAuthorized;
}
_onWeatherProxyReady(o, res) {
try {
this._weatherProxy = Gio.DBusProxy.new_finish(res);
} catch (e) {
log(`Failed to create GNOME Weather proxy: ${e}`);
return;
}
this._weatherProxy.connect('g-properties-changed',
this._onWeatherPropertiesChanged.bind(this));
if (this._weatherProxy.g_name_owner != null)
this._onWeatherPropertiesChanged();
}
_onWeatherPropertiesChanged() {
this._settings.set_boolean('automatic-location',
this._weatherProxy.AutomaticLocation);
this._settings.set_value('locations',
new GLib.Variant('av', this._weatherProxy.Locations));
}
_onInstalledChanged() {
let hadApp = (this._weatherApp != null);
this._weatherApp = this._appSystem.lookup_app(WEATHER_APP_ID);
let haveApp = (this._weatherApp != null);
if (hadApp !== haveApp)
this.emit('changed');
}
_loadInfo() {
let id = this._weatherInfo.connect('updated', () => {
this._weatherInfo.disconnect(id);
@@ -234,7 +294,7 @@ var WeatherClient = class {
}
_onPermStoreChanged(proxy, sender, params) {
let [table, id, deleted, data, perms] = params;
let [table, id, deleted_, data_, perms] = params;
if (table != 'gnome' || id != 'geolocation')
return;

View File

@@ -1,4 +1,9 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported run, script_overviewShowStart, script_overviewShowDone,
script_applicationsShowStart, script_applicationsShowDone,
script_afterShowHide, malloc_usedSize, glx_swapComplete,
clutter_stagePaintDone */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^malloc", "^glx", "^clutter"] }] */
const System = imports.system;
@@ -121,9 +126,11 @@ function *run() {
for (let i = 0; i < 2; i++) {
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
Scripting.scriptEvent('applicationsShowDone');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = false;
yield Scripting.waitLeisure();
}
@@ -147,7 +154,7 @@ function script_overviewShowStart(time) {
overviewFrames = 0;
}
function script_overviewShowDone(time) {
function script_overviewShowDone(_time) {
// We've set up the state at the end of the zoom out, but we
// need to wait for one more frame to paint before we count
// ourselves as done.
@@ -166,7 +173,7 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTimeSubsequent.value = time - applicationsShowStart;
}
function script_afterShowHide(time) {
function script_afterShowHide(_time) {
if (overviewShowCount == 1) {
METRICS.usedAfterOverview.value = mallocUsedSize;
} else {

View File

@@ -1,3 +1,12 @@
/* exported run, script_desktopShown, script_overviewShowStart,
script_overviewShowDone, script_applicationsShowStart,
script_applicationsShowDone, script_mainViewDrawStart,
script_mainViewDrawDone, script_overviewDrawStart,
script_overviewDrawDone, script_redrawTestStart,
script_redrawTestDone, script_collectTimings,
script_geditLaunch, script_geditFirstFrame,
clutter_stagePaintStart, clutter_paintCompletedTimestamp */
/* eslint camelcase: ["error", { properties: "never", allow: ["^script_", "^clutter"] }] */
const { Clutter, Gio, Shell } = imports.gi;
const Main = imports.ui.main;
const Scripting = imports.ui.scripting;
@@ -38,7 +47,7 @@ function waitAndDraw(milliseconds) {
let timeline = new Clutter.Timeline({ duration: milliseconds });
timeline.start();
timeline.connect('new-frame', (timeline, frame) => {
timeline.connect('new-frame', (_timeline, _frame) => {
global.stage.queue_redraw();
});
@@ -73,8 +82,8 @@ function extractBootTimestamp() {
let result = null;
let datastream = Gio.DataInputStream.new(sp.get_stdout_pipe());
while (true) {
let [line, length] = datastream.read_line_utf8(null);
while (true) { // eslint-disable-line no-constant-condition
let [line, length_] = datastream.read_line_utf8(null);
if (line === null)
break;
@@ -117,6 +126,7 @@ function *run() {
yield Scripting.sleep(1000);
Scripting.scriptEvent('applicationsShowStart');
// eslint-disable-next-line require-atomic-updates
Main.overview._dash.showAppsButton.checked = true;
yield Scripting.waitLeisure();
@@ -234,31 +244,31 @@ function script_applicationsShowDone(time) {
METRICS.applicationsShowTime.value = time - applicationsShowStart;
}
function script_mainViewDrawStart(time) {
function script_mainViewDrawStart(_time) {
redrawTiming = 'mainView';
}
function script_mainViewDrawDone(time) {
function script_mainViewDrawDone(_time) {
redrawTiming = null;
}
function script_overviewDrawStart(time) {
function script_overviewDrawStart(_time) {
redrawTiming = 'overview';
}
function script_overviewDrawDone(time) {
function script_overviewDrawDone(_time) {
redrawTiming = null;
}
function script_redrawTestStart(time) {
function script_redrawTestStart(_time) {
redrawTiming = 'application';
}
function script_redrawTestDone(time) {
function script_redrawTestDone(_time) {
redrawTiming = null;
}
function script_collectTimings(time) {
function script_collectTimings(_time) {
for (let timing in redrawTimes) {
let times = redrawTimes[timing];
times.sort((a, b) => a - b);

View File

@@ -1,3 +1,4 @@
/* exported main */
const Format = imports.format;
const Gettext = imports.gettext;
const { Gio, GLib, GObject, Gtk, Pango, Soup, WebKit2: WebKit } = imports.gi;
@@ -151,7 +152,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._webView.load_uri(this._originalUrl);
}
vfunc_delete_event(event) {
vfunc_delete_event(_event) {
if (this._recheckAtExit)
this._doneCallback(PortalHelperResult.RECHECK);
else
@@ -177,7 +178,7 @@ class PortalWindow extends Gtk.ApplicationWindow {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
}
_onLoadFailedWithTlsErrors(view, failingURI, certificate, errors) {
_onLoadFailedWithTlsErrors(view, failingURI, certificate, _errors) {
this._headerBar.setSecurityIcon(PortalHelperSecurityLevel.INSECURE);
let uri = new Soup.URI(failingURI);
this._webContext.allow_tls_certificate_for_host(certificate, uri.get_host());

View File

@@ -1,3 +1,4 @@
/* exported AccessDialogDBus */
const { Clutter, Gio, GLib, GObject, Shell } = imports.gi;
const CheckBox = imports.ui.checkBox;
@@ -79,7 +80,7 @@ class AccessDialog extends ModalDialog.ModalDialog {
this._requestExported = this._request.export(connection, this._handle);
}
CloseAsync(invocation, params) {
CloseAsync(invocation, _params) {
if (this._invocation.get_sender() != invocation.get_sender()) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
@@ -132,7 +133,7 @@ var AccessDialogDBus = class {
return;
}
let [handle, appId, parentWindow, title, subtitle, body, options] = params;
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) {

View File

@@ -1,4 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported AppSwitcherPopup, GroupCyclerPopup, WindowSwitcherPopup,
WindowCyclerPopup */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -87,9 +89,9 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
let hPadding = leftPadding + rightPadding;
let icon = this._items[this._selectedIndex];
let [posX, posY] = icon.get_transformed_position();
let [posX] = icon.get_transformed_position();
let thumbnailCenter = posX + icon.width / 2;
let [childMinWidth, childNaturalWidth] = this._thumbnails.get_preferred_width(-1);
let [, childNaturalWidth] = this._thumbnails.get_preferred_width(-1);
childBox.x1 = Math.max(primary.x + leftPadding, Math.floor(thumbnailCenter - childNaturalWidth / 2));
if (childBox.x1 + childNaturalWidth > primary.x + primary.width - hPadding) {
let offset = childBox.x1 + childNaturalWidth - primary.width + hPadding;
@@ -103,7 +105,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
childBox.x2 = primary.x + primary.width - rightPadding;
childBox.y1 = this._switcherList.allocation.y2 + spacing;
this._thumbnails.addClones(primary.y + primary.height - bottomPadding - childBox.y1);
let [childMinHeight, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
let [, childNaturalHeight] = this._thumbnails.get_preferred_height(-1);
childBox.y2 = childBox.y1 + childNaturalHeight;
this._thumbnails.allocate(childBox, flags);
}
@@ -469,7 +471,7 @@ var CyclerList = GObject.registerClass({
'item-removed': { param_types: [GObject.TYPE_INT] },
'item-highlighted': { param_types: [GObject.TYPE_INT] } },
}, class CyclerList extends St.Widget {
highlight(index, justOutline) {
highlight(index, _justOutline) {
this.emit('item-highlighted', index);
}
});
@@ -494,7 +496,7 @@ var CyclerPopup = GObject.registerClass({
});
}
_highlightItem(index, justOutline) {
_highlightItem(index, _justOutline) {
this._highlight.window = this._items[index];
global.window_group.set_child_above_sibling(this._highlight.actor, null);
}
@@ -660,6 +662,7 @@ class AppIcon extends St.BoxLayout {
this.add(this.label, { x_fill: false });
}
// eslint-disable-next-line camelcase
set_size(size) {
this.icon = this.app.create_icon_texture(size);
this._iconBin.child = this.icon;
@@ -801,7 +804,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
}
_enterItem(index) {
let [x, y, mask] = global.get_pointer();
let [x, y] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.ALL, x, y);
if (this._items[index].contains(pickedActor))
this._itemEntered(index);
@@ -908,7 +911,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
return;
let totalPadding = this._items[0].get_theme_node().get_horizontal_padding() + this._items[0].get_theme_node().get_vertical_padding();
totalPadding += this.get_theme_node().get_horizontal_padding() + this.get_theme_node().get_vertical_padding();
let [labelMinHeight, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let [, labelNaturalHeight] = this._labels[0].get_preferred_height(-1);
let spacing = this._items[0].child.get_theme_node().get_length('spacing');
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
let thumbnailSize = THUMBNAIL_DEFAULT_SIZE * scaleFactor;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Animation, AnimatedIcon, Spinner */
const { GLib, Gio, St } = imports.gi;
const Mainloop = imports.mainloop;

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getAppFavorites */
const Shell = imports.gi.Shell;
const Signals = imports.signals;

View File

@@ -1,3 +1,4 @@
/* exported AudioDeviceSelectionDBus */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Main = imports.ui.main;
@@ -34,7 +35,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
throw new Error('Too few devices for a selection');
}
_buildLayout(devices) {
_buildLayout() {
let title = new St.Label({ style_class: 'audio-selection-title',
text: _("Select Audio Device"),
x_align: Clutter.ActorAlign.CENTER });
@@ -85,6 +86,7 @@ var AudioDeviceSelectionDialog = GObject.registerClass({
box.connect('notify::height', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
box.width = box.height;
return GLib.SOURCE_REMOVE;
});
});

View File

@@ -333,12 +333,12 @@ var Background = class Background {
}
_loadPattern() {
let colorString, res, color, secondColor;
let colorString, res_, color, secondColor;
colorString = this._settings.get_string(PRIMARY_COLOR_KEY);
[res, color] = Clutter.Color.from_string(colorString);
[res_, color] = Clutter.Color.from_string(colorString);
colorString = this._settings.get_string(SECONDARY_COLOR_KEY);
[res, secondColor] = Clutter.Color.from_string(colorString);
[res_, secondColor] = Clutter.Color.from_string(colorString);
let shadingType = this._settings.get_enum(COLOR_SHADING_TYPE_KEY);
@@ -633,9 +633,9 @@ 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._show.load_async(null, () => {
this.loaded = true;
if (callback)
callback();
@@ -651,7 +651,7 @@ var Animation = class Animation {
if (this._show.get_num_slides() < 1)
return;
let [progress, duration, isFixed, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
let [progress, duration, isFixed_, filename1, filename2] = this._show.get_current_slide(monitor.width, monitor.height);
this.transitionDuration = duration;
this.transitionProgress = progress;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addBackgroundMenu */
const { Clutter, St } = imports.gi;

View File

@@ -1,10 +1,11 @@
/* -*- mode: js2; js2-basic-offset: 4; indent-tabs-mode: nil -*- */
/* exported BarLevel */
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 +14,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,
@@ -36,26 +34,56 @@ var BarLevel = class {
this.connect('value-changed', this._valueChanged.bind(this));
}
setValue(value) {
get value() {
return this._value;
}
set value(value) {
if (isNaN(value))
throw TypeError('The bar level value must be a number');
this._value = Math.max(Math.min(value, this._maxValue), 0);
value = Math.max(Math.min(value, this._maxValue), 0);
if (this._value == value)
return;
this._value = value;
this.actor.queue_repaint();
}
setMaximumValue(value) {
// eslint-disable-next-line camelcase
get maximum_value() {
return this._maxValue;
}
// eslint-disable-next-line camelcase
set maximum_value(value) {
if (isNaN(value))
throw TypeError('The bar level max value must be a number');
this._maxValue = Math.max(value, 1);
value = Math.max(value, 1);
if (this._maxValue == value)
return;
this._maxValue = value;
this._overdriveStart = Math.min(this._overdriveStart, this._maxValue);
this.actor.queue_repaint();
}
setOverdriveStart(value) {
// eslint-disable-next-line camelcase
get overdrive_start() {
return this._overdriveStart;
}
// eslint-disable-next-line camelcase
set overdrive_start(value) {
if (isNaN(value))
throw TypeError('The overdrive limit value must be a number');
if (this._overdriveStart == value)
return;
if (value > this._maxValue)
throw new Error(`Tried to set overdrive value to ${value}, ` +
`which is a number greater than the maximum allowed value ${this._maxValue}`);
@@ -175,32 +203,28 @@ var BarLevel = class {
cr.$dispose();
}
_getCurrentValue(actor) {
_getCurrentValue() {
return this._value;
}
_getOverdriveStart(actor) {
_getOverdriveStart() {
return this._overdriveStart;
}
_getMinimumValue(actor) {
_getMinimumValue() {
return 0;
}
_getMaximumValue(actor) {
_getMaximumValue() {
return this._maxValue;
}
_setCurrentValue(actor, value) {
_setCurrentValue(_actor, value) {
this._value = value;
}
_valueChanged(barLevel, value, property) {
_valueChanged() {
this._customAccessible.notify("accessible-value");
}
get value() {
return this._value;
}
};
Signals.addSignalMethods(BarLevel.prototype);

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BoxPointer */
const { Clutter, GObject, Shell, St } = imports.gi;
@@ -469,7 +470,7 @@ var BoxPointer = GObject.registerClass({
let sourceAllocation = this._sourceAllocation;
let sourceCenterX = sourceAllocation.x1 + sourceContentBox.x1 + (sourceContentBox.x2 - sourceContentBox.x1) * this._sourceAlignment;
let sourceCenterY = sourceAllocation.y1 + sourceContentBox.y1 + (sourceContentBox.y2 - sourceContentBox.y1) * this._sourceAlignment;
let [minWidth, minHeight, natWidth, natHeight] = this.get_preferred_size();
let [, , natWidth, natHeight] = this.get_preferred_size();
// We also want to keep it onscreen, and separated from the
// edge by the same distance as the main part of the box is
@@ -594,7 +595,7 @@ var BoxPointer = GObject.registerClass({
_calculateArrowSide(arrowSide) {
let sourceAllocation = this._sourceAllocation;
let [minWidth, minHeight, boxWidth, boxHeight] = this.get_preferred_size();
let [, , boxWidth, boxHeight] = this.get_preferred_size();
let workarea = this._workArea;
switch (arrowSide) {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -109,15 +110,15 @@ var EmptyEventSource = class EmptyEventSource {
destroy() {
}
requestRange(begin, end) {
requestRange(_begin, _end) {
}
getEvents(begin, end) {
getEvents(_begin, _end) {
let result = [];
return result;
}
hasEvents(day) {
hasEvents(_day) {
return false;
}
};
@@ -220,13 +221,13 @@ var DBusEventSource = class DBusEventSource {
this._lastRequestEnd = null;
}
_onNameAppeared(owner) {
_onNameAppeared() {
this._initialized = true;
this._resetCache();
this._loadEvents(true);
}
_onNameVanished(oldOwner) {
_onNameVanished() {
this._resetCache();
this.emit('changed');
}
@@ -235,22 +236,20 @@ var DBusEventSource = class DBusEventSource {
this._loadEvents(false);
}
_onEventsReceived(results, error) {
_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;
@@ -736,7 +735,7 @@ class NotificationMessage extends MessageList.Message {
return this.notification.source.createIcon(MESSAGE_ICON_SIZE);
}
_onUpdated(n, clear) {
_onUpdated(n, _clear) {
this.setIcon(this._getIcon());
this.setTitle(n.title);
this.setBody(n.bannerBodyText);

View File

@@ -1,3 +1,4 @@
/* exported CheckBox */
const { Clutter, Pango, St } = imports.gi;
var CheckBox = class CheckBox {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;

View File

@@ -1,3 +1,4 @@
/* exported ComponentManager */
const Main = imports.ui.main;
var ComponentManager = class {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
@@ -55,7 +56,7 @@ var AutomountManager = class {
}
}
_InhibitorsChanged(object, senderName, [inhibtor]) {
_InhibitorsChanged(_object, _senderName, [_inhibitor]) {
this._session.IsInhibitedRemote(GNOME_SESSION_AUTOMOUNT_INHIBIT,
(result, error) => {
if (!error) {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Gio, St } = imports.gi;
@@ -122,10 +123,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')

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gcr, Gio, GObject, Pango, Shell, St } = imports.gi;
@@ -176,21 +177,21 @@ class KeyringDialog extends ModalDialog.ModalDialog {
return false;
}
_onShowPassword(prompt) {
_onShowPassword() {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._passwordEntry.grab_key_focus();
}
_onShowConfirm(prompt) {
_onShowConfirm() {
this._buildControlTable();
this._ensureOpen();
this._updateSensitivity(true);
this._continueButton.grab_key_focus();
}
_onHidePrompt(prompt) {
_onHidePrompt() {
this.close();
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -199,7 +200,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
return true;
}
_getWirelessSecrets(secrets, wirelessSetting) {
_getWirelessSecrets(secrets, _wirelessSetting) {
let wirelessSecuritySetting = this._connection.get_setting_wireless_security();
if (this._settingName == '802-1x') {
@@ -385,7 +386,7 @@ var VPNRequestHandler = class {
this._newStylePlugin = authHelper.externalUIMode;
try {
let [success, pid, stdin, stdout, stderr] =
let [success_, pid, stdin, stdout, stderr] =
GLib.spawn_async_with_pipes(null, /* pwd */
argv,
null, /* envp */
@@ -444,7 +445,7 @@ var VPNRequestHandler = class {
this._destroyed = true;
}
_vpnChildFinished(pid, status, requestObj) {
_vpnChildFinished(pid, status, _requestObj) {
this._childWatch = 0;
if (this._newStylePlugin) {
// For new style plugin, all work is done in the async reading functions
@@ -486,7 +487,7 @@ var VPNRequestHandler = class {
_readStdoutOldStyle() {
this._dataStdout.read_line_async(GLib.PRIORITY_DEFAULT, null, (stream, result) => {
let [line, len] = this._dataStdout.read_line_finish_utf8(result);
let [line, len_] = this._dataStdout.read_line_finish_utf8(result);
if (line == null) {
// end of file
@@ -541,7 +542,7 @@ var VPNRequestHandler = class {
message: keyfile.get_string(VPN_UI_GROUP, 'Description'),
secrets: [] };
let [groups, len] = keyfile.get_groups();
let [groups, len_] = keyfile.get_groups();
for (let i = 0; i < groups.length; i++) {
if (groups[i] == VPN_UI_GROUP)
continue;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { AccountsService, Clutter, Gio, GLib,
GObject, Pango, PolkitAgent, Polkit, Shell, St } = imports.gi;
@@ -383,11 +384,11 @@ var AuthenticationAgent = class {
this._currentDialog.performAuthentication();
}
_onCancel(nativeAgent) {
_onCancel(_nativeAgent) {
this._completeRequest(false);
}
_onDialogDone(dialog, dismissed) {
_onDialogDone(_dialog, dismissed) {
this._completeRequest(dismissed);
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Component */
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
@@ -41,7 +42,7 @@ var NotificationDirection = {
};
function makeMessageFromTpMessage(tpMessage, direction) {
let [text, flags] = tpMessage.to_text();
let [text, flags_] = tpMessage.to_text();
let timestamp = tpMessage.get_sent_timestamp();
if (timestamp == 0)
@@ -148,11 +149,11 @@ class TelepathyClient extends Tp.BaseClient {
}
vfunc_observe_channels(...args) {
let [account, conn, channels, dispatchOp, requests, context] = 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();
let [targetHandle_, targetHandleType] = channel.get_handle();
if (channel.get_invalidated())
continue;
@@ -181,7 +182,7 @@ class TelepathyClient extends Tp.BaseClient {
}
vfunc_handle_channels(...args) {
let [account, conn, channels, requests, userActionTime, context] = args;
let [account, conn, channels, requests_, userActionTime_, context] = args;
this._handlingChannels(account, conn, channels, true);
context.accept();
}
@@ -239,7 +240,7 @@ class TelepathyClient extends Tp.BaseClient {
}
_approveTextChannel(account, conn, channel, dispatchOp, context) {
let [targetHandle, targetHandleType] = channel.get_handle();
let [targetHandle_, targetHandleType] = channel.get_handle();
if (targetHandleType != Tp.HandleType.CONTACT) {
context.fail(new Tp.Error({ code: Tp.Error.INVALID_ARGUMENT,
@@ -260,7 +261,7 @@ class TelepathyClient extends Tp.BaseClient {
context.accept();
}
_delegatedChannelsCb(client, channels) {
_delegatedChannelsCb(_client, _channels) {
// Nothing to do as we don't make a distinction between observed and
// handled channels.
}
@@ -427,7 +428,7 @@ var ChatSource = class extends MessageTray.Source {
}
_displayPendingMessages(logManager, result) {
let [success, events] = logManager.get_filtered_events_finish(result);
let [success_, events] = logManager.get_filtered_events_finish(result);
let logMessages = events.map(makeMessageFromTplEvent);
this._ensureNotification();
@@ -562,7 +563,7 @@ var ChatSource = class extends MessageTray.Source {
// This is called for both messages we send from
// our client and other clients as well.
_messageSent(channel, message, flags, token) {
_messageSent(channel, message, _flags, _token) {
this._ensureNotification();
message = makeMessageFromTpMessage(message, NotificationDirection.SENT);
this._notification.appendMessage(message);
@@ -600,7 +601,7 @@ var ChatSource = class extends MessageTray.Source {
}
}
_presenceChanged(contact, presence, status, message) {
_presenceChanged(_contact, _presence, _status, _message) {
if (this._notification)
this._notification.update(this._notification.title,
this._notification.bannerBodyText,

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CtrlAltTabManager */
const { Clutter, GObject, Meta, Shell, St } = imports.gi;
@@ -63,9 +64,8 @@ var CtrlAltTabManager = class CtrlAltTabManager {
if (a.sortGroup != b.sortGroup)
return a.sortGroup - b.sortGroup;
let ax, bx, y;
[ax, y] = a.proxy.get_transformed_position();
[bx, y] = b.proxy.get_transformed_position();
let [ax] = a.proxy.get_transformed_position();
let [bx] = b.proxy.get_transformed_position();
return ax - bx;
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -24,6 +25,32 @@ function getAppFromSource(source) {
}
}
var DashIcon = class DashIcon extends AppDisplay.AppIcon {
constructor(app) {
super(app, null, {
setSizeManually: true,
showLabel: false
});
}
// Disable all DnD methods
_onDragBegin() {
}
_onDragEnd() {
}
handleDragOver() {
return DND.DragMotionResult.CONTINUE;
}
acceptDrop() {
return false;
}
}
// A container like StBin, but taking the child's scale into account
// when requesting a size
var DashItemContainer = GObject.registerClass(
@@ -241,14 +268,14 @@ class ShowAppsIcon extends DashItemContainer {
this.setLabelText(_("Show Applications"));
}
handleDragOver(source, actor, x, y, time) {
handleDragOver(source, _actor, _x, _y, _time) {
if (!this._canRemoveApp(getAppFromSource(source)))
return DND.DragMotionResult.NO_DROP;
return DND.DragMotionResult.MOVE_DROP;
}
acceptDrop(source, actor, x, y, time) {
acceptDrop(source, _actor, _x, _y, _time) {
let app = getAppFromSource(source);
if (!this._canRemoveApp(app))
return false;
@@ -296,7 +323,7 @@ class DashActor extends St.Widget {
this.set_allocation(box, flags);
let [appIcons, showAppsButton] = this.get_children();
let [showAppsMinHeight, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
let [, showAppsNatHeight] = showAppsButton.get_preferred_height(availWidth);
let childBox = new Clutter.ActorBox();
childBox.x1 = contentBox.x1;
@@ -474,19 +501,7 @@ var Dash = class Dash {
}
_createAppItem(app) {
let appIcon = new AppDisplay.AppIcon(app,
{ setSizeManually: true,
showLabel: false });
if (appIcon._draggable) {
appIcon._draggable.connect('drag-begin',
() => {
appIcon.actor.opacity = 50;
});
appIcon._draggable.connect('drag-end',
() => {
appIcon.actor.opacity = 255;
});
}
let appIcon = new DashIcon(app);
appIcon.connect('menu-state-changed',
(appIcon, opened) => {
@@ -790,7 +805,7 @@ var Dash = class Dash {
}
}
handleDragOver(source, actor, x, y, time) {
handleDragOver(source, actor, x, y, _time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps
@@ -868,7 +883,7 @@ var Dash = class Dash {
}
// Draggable target interface
acceptDrop(source, actor, x, y, time) {
acceptDrop(source, _actor, _x, _y, _time) {
let app = getAppFromSource(source);
// Don't allow favoriting of transient apps

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported DateMenuButton */
const { Clutter, GLib, GnomeDesktop,
GObject, GWeather, Shell, St } = imports.gi;
@@ -249,12 +250,12 @@ var WeatherSection = class WeatherSection {
let current = info;
let infos = [info];
for (let i = 0; i < forecasts.length; i++) {
let [ok, timestamp] = forecasts[i].get_value_update();
let [ok_, timestamp] = forecasts[i].get_value_update();
let datetime = new Date(timestamp * 1000);
if (!_isToday(datetime))
continue; // Ignore forecasts from other days
[ok, timestamp] = current.get_value_update();
[ok_, timestamp] = current.get_value_update();
let currenttime = new Date(timestamp * 1000);
if (currenttime.getHours() == datetime.getHours())
continue; // Enforce a minimum interval of 1h
@@ -275,7 +276,7 @@ var WeatherSection = class WeatherSection {
let col = 0;
infos.forEach(fc => {
let [ok, timestamp] = fc.get_value_update();
let [ok_, timestamp] = fc.get_value_update();
let timeStr = Util.formatTime(new Date(timestamp * 1000), {
timeOnly: true
});

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Dialog, MessageDialogContent */
const { Clutter, Gio, GObject, Pango, St } = imports.gi;
@@ -180,10 +181,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,

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported addDragMonitor, removeDragMonitor, makeDraggable */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -503,7 +504,7 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.handleDragOver) {
let [r, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
let [r_, targX, targY] = target.transform_stage_point(this._dragX, this._dragY);
// We currently loop through all parents on drag-over even if one of the children has handled it.
// We can check the return value of the function and break the loop if it's true if we don't want
// to continue checking the parents.
@@ -575,7 +576,7 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [r, targX, targY] = target.transform_stage_point(dropX, dropY);
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
@@ -613,15 +614,15 @@ var _Draggable = class _Draggable {
if (this._dragActorSource && this._dragActorSource.visible) {
// Snap the clone back to its source
[x, y] = this._dragActorSource.get_transformed_position();
let [sourceScaledWidth, sourceScaledHeight] = this._dragActorSource.get_transformed_size();
let [sourceScaledWidth] = this._dragActorSource.get_transformed_size();
scale = sourceScaledWidth ? this._dragActor.width / sourceScaledWidth : 0;
} else if (this._dragOrigParent) {
// Snap the actor back to its original position within
// its parent, adjusting for the fact that the parent
// may have been moved or scaled
let [parentX, parentY] = this._dragOrigParent.get_transformed_position();
let [parentWidth, parentHeight] = this._dragOrigParent.get_size();
let [parentScaledWidth, parentScaledHeight] = this._dragOrigParent.get_transformed_size();
let [parentWidth] = this._dragOrigParent.get_size();
let [parentScaledWidth] = this._dragOrigParent.get_transformed_size();
let parentScale = 1.0;
if (parentWidth != 0)
parentScale = parentScaledWidth / parentWidth;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported EdgeDragAction */
const { Clutter, GObject, Meta, St } = imports.gi;
@@ -26,7 +27,7 @@ var EdgeDragAction = GObject.registerClass({
return global.display.get_monitor_geometry(monitorIndex);
}
vfunc_gesture_prepare(actor) {
vfunc_gesture_prepare(_actor) {
if (this.get_n_current_points() == 0)
return false;
@@ -42,7 +43,7 @@ var EdgeDragAction = GObject.registerClass({
(this._side == St.Side.BOTTOM && y > monitorRect.y + monitorRect.height - EDGE_THRESHOLD));
}
vfunc_gesture_progress(actor) {
vfunc_gesture_progress(_actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let offsetX = Math.abs (x - startX);
@@ -62,7 +63,7 @@ var EdgeDragAction = GObject.registerClass({
return true;
}
vfunc_gesture_end(actor) {
vfunc_gesture_end(_actor) {
let [startX, startY] = this.get_press_coords(0);
let [x, y] = this.get_motion_coords(0);
let monitorRect = this._getMonitorRect(startX, startY);

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, EndSessionDialog */
/*
* Copyright 2010-2016 Red Hat, Inc
*
@@ -353,8 +354,8 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
// It only makes sense to check for this permission if PackageKit is available.
try {
this._updatesPermission = Polkit.Permission.new_sync(
"org.freedesktop.packagekit.trigger-offline-update", null, null);
} catch(e) {
'org.freedesktop.packagekit.trigger-offline-update', null, null);
} catch (e) {
log('No permission to trigger offline updates: %s'.format(e.toString()));
}
}
@@ -668,7 +669,7 @@ 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')
@@ -734,7 +735,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
let dialogContent = DialogContent[this._type];
for (let i = 0; i < inhibitorObjectPaths.length; i++) {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], (proxy, error) => {
let inhibitor = new GnomeSession.Inhibitor(inhibitorObjectPaths[i], proxy => {
this._onInhibitorLoaded(proxy);
});
@@ -778,7 +779,7 @@ class EndSessionDialog extends ModalDialog.ModalDialog {
});
}
Close(parameters, invocation) {
Close(_parameters, _invocation) {
this.close();
}
});

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init */
const Config = imports.misc.config;
@@ -106,6 +107,12 @@ function init() {
}
});
St.set_slow_down_factor = function(factor) {
let { stack } = new Error();
log(`St.set_slow_down_factor() is deprecated, use St.Settings.slow_down_factor\n${stack}`);
St.Settings.get().slow_down_factor = factor;
};
let origToString = Object.prototype.toString;
Object.prototype.toString = function() {
let base = origToString.call(this);
@@ -128,7 +135,7 @@ function init() {
if (slowdownEnv) {
let factor = parseFloat(slowdownEnv);
if (!isNaN(factor) && factor > 0.0)
St.set_slow_down_factor(factor);
St.Settings.get().slow_down_factor = factor;
}
// OK, now things are initialized enough that we can import shell JS

View File

@@ -1,12 +1,14 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init, installExtension, uninstallExtension,
checkForUpdates, updateExtension */
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;
var REPOSITORY_URL_BASE = 'https://extensions.gnome.org';
@@ -24,7 +26,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;
}
@@ -33,7 +35,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;
}
@@ -44,7 +46,7 @@ function installExtension(uuid, invocation) {
}
function uninstallExtension(uuid) {
let extension = ExtensionUtils.extensions[uuid];
let extension = Main.extensionManager.lookup(uuid);
if (!extension)
return false;
@@ -52,7 +54,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);
@@ -113,10 +115,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);
@@ -125,11 +127,11 @@ function updateExtension(uuid) {
let extension = null;
try {
extension = ExtensionUtils.createExtensionObject(uuid, extensionDir, ExtensionUtils.ExtensionType.PER_USER);
ExtensionSystem.loadExtension(extension);
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));
@@ -138,7 +140,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;
}
@@ -151,9 +153,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) };
@@ -203,12 +205,12 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
this.contentLayout.add(content);
}
_onCancelButtonPressed(button, event) {
_onCancelButtonPressed() {
this.close();
this._invocation.return_value(GLib.Variant.new('(s)', ['cancelled']));
}
_onInstallButtonPressed(button, event) {
_onInstallButtonPressed() {
let params = { shell_version: Config.PACKAGE_VERSION };
let url = REPOSITORY_URL_DOWNLOAD.format(this._uuid);
@@ -224,16 +226,11 @@ class InstallExtensionDialog extends ModalDialog.ModalDialog {
}
function callback() {
// Add extension to 'enabled-extensions' for the user, always...
let enabledExtensions = global.settings.get_strv(ExtensionSystem.ENABLED_EXTENSIONS_KEY);
if (!enabledExtensions.includes(uuid)) {
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);
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);

View File

@@ -1,374 +1,523 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
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()];
}
_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;
}
for (let i = 0; i < orderReversed.length; i++) {
let uuid = orderReversed[i];
try {
ExtensionUtils.extensions[uuid].stateObj.disable();
extension.stateObj.disable();
} catch (e) {
logExtensionError(uuid, e);
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);
}
}
if (extension.stylesheet) {
_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();
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);
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;
}
}
}
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.enable();
extension.state = ExtensionState.ENABLED;
this.emit('extension-state-changed', extension);
return;
} 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}`);
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.includes(extension.uuid);
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);
[success_, metadataContents] = metadataFile.load_contents(null);
if (metadataContents instanceof Uint8Array)
metadataContents = imports.byteArray.toString(metadataContents);
} catch (e) {
logExtensionError(uuid, 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

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported GrabHelper */
const { Clutter, St } = imports.gi;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CandidatePopup */
const { Clutter, IBus, St } = imports.gi;
const Signals = imports.signals;
@@ -198,29 +199,29 @@ var CandidatePopup = class CandidatePopup {
this._setTextAttributes(this._preeditText.clutter_text,
attrs);
});
panelService.connect('show-preedit-text', ps => {
panelService.connect('show-preedit-text', () => {
this._preeditText.show();
this._updateVisibility();
});
panelService.connect('hide-preedit-text', ps => {
panelService.connect('hide-preedit-text', () => {
this._preeditText.hide();
this._updateVisibility();
});
panelService.connect('update-auxiliary-text', (ps, text, visible) => {
panelService.connect('update-auxiliary-text', (_ps, text, visible) => {
this._auxText.visible = visible;
this._updateVisibility();
this._auxText.text = text.get_text();
});
panelService.connect('show-auxiliary-text', ps => {
panelService.connect('show-auxiliary-text', () => {
this._auxText.show();
this._updateVisibility();
});
panelService.connect('hide-auxiliary-text', ps => {
panelService.connect('hide-auxiliary-text', () => {
this._auxText.hide();
this._updateVisibility();
});
panelService.connect('update-lookup-table', (ps, lookupTable, visible) => {
panelService.connect('update-lookup-table', (_ps, lookupTable, visible) => {
this._candidateArea.actor.visible = visible;
this._updateVisibility();
@@ -256,15 +257,15 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.setOrientation(lookupTable.get_orientation());
this._candidateArea.updateButtons(lookupTable.is_round(), page, nPages);
});
panelService.connect('show-lookup-table', ps => {
panelService.connect('show-lookup-table', () => {
this._candidateArea.actor.show();
this._updateVisibility();
});
panelService.connect('hide-lookup-table', ps => {
panelService.connect('hide-lookup-table', () => {
this._candidateArea.actor.hide();
this._updateVisibility();
});
panelService.connect('focus-out', ps => {
panelService.connect('focus-out', () => {
this._boxPointer.close(BoxPointer.PopupAnimation.NONE);
Main.keyboard.resetSuggestions();
});

View File

@@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported BaseIcon, IconGrid, PaginatedIconGrid */
const { Clutter, GObject, Meta, St } = imports.gi;
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Params = imports.misc.params;
const Tweener = imports.ui.tweener;
@@ -28,6 +29,27 @@ var AnimationDirection = {
var APPICON_ANIMATION_OUT_SCALE = 3;
var APPICON_ANIMATION_OUT_TIME = 0.25;
const LEFT_DIVIDER_LEEWAY = 30;
const RIGHT_DIVIDER_LEEWAY = 30;
const NUDGE_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_ELASTIC;
const NUDGE_DURATION = 800;
const NUDGE_RETURN_ANIMATION_TYPE = Clutter.AnimationMode.EASE_OUT_QUINT;
const NUDGE_RETURN_DURATION = 300;
const NUDGE_FACTOR = 0.33;
const ICON_POSITION_DELAY = 25;
var DragLocation = {
DEFAULT: 0,
ON_ICON: 1,
START_EDGE: 2,
END_EDGE: 3,
EMPTY_AREA: 4,
}
var BaseIcon = GObject.registerClass(
class BaseIcon extends St.Bin {
_init(label, params) {
@@ -56,6 +78,10 @@ class BaseIcon extends St.Bin {
if (params.showLabel) {
this.label = new St.Label({ text: label });
this.label.clutter_text.set({
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.CENTER
});
this._box.add_actor(this.label);
} else {
this.label = null;
@@ -71,14 +97,14 @@ class BaseIcon extends St.Bin {
this._iconThemeChangedId = cache.connect('icon-theme-changed', this._onIconThemeChanged.bind(this));
}
vfunc_get_preferred_width(forHeight) {
vfunc_get_preferred_width(_forHeight) {
// Return the actual height to keep the squared aspect
return this.get_preferred_height(-1);
}
// This can be overridden by a subclass, or by the createIcon
// parameter to _init()
createIcon(size) {
createIcon(_size) {
throw new GObject.NotImplementedError(`createIcon in ${this.constructor.name}`);
}
@@ -137,6 +163,10 @@ class BaseIcon extends St.Bin {
// animating.
zoomOutActor(this.child);
}
update() {
this._createIconTexture(this.iconSize);
}
});
function clamp(value, min, max) {
@@ -206,6 +236,8 @@ var IconGrid = GObject.registerClass({
this.rightPadding = 0;
this.leftPadding = 0;
this._updateIconSizesLaterId = 0;
this._items = [];
this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here
@@ -223,6 +255,14 @@ var IconGrid = GObject.registerClass({
this.connect('actor-added', this._childAdded.bind(this));
this.connect('actor-removed', this._childRemoved.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
_onDestroy() {
if (this._updateIconSizesLaterId) {
Meta.later_remove (this._updateIconSizesLaterId);
this._updateIconSizesLaterId = 0;
}
}
_keyFocusIn(actor) {
@@ -237,7 +277,7 @@ var IconGrid = GObject.registerClass({
child.disconnect(child._iconGridKeyFocusInId);
}
vfunc_get_preferred_width(forHeight) {
vfunc_get_preferred_width(_forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
@@ -327,6 +367,7 @@ var IconGrid = GObject.registerClass({
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let rowIndex = 0;
let nChanged = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
@@ -336,7 +377,16 @@ var IconGrid = GObject.registerClass({
} else {
if (!animating)
children[i].opacity = 255;
// Figure out how much delay to apply
if (!childBox.equal(children[i].get_allocation_box()))
nChanged++;
children[i].save_easing_state();
children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged);
children[i].allocate(childBox, flags);
children[i].restore_easing_state();
}
columnIndex++;
@@ -602,6 +652,8 @@ var IconGrid = GObject.registerClass({
}
_computeLayout(forWidth) {
this.ensure_style();
let nColumns = 0;
let usedWidth = this.leftPadding + this.rightPadding;
let spacing = this._getSpacing();
@@ -674,6 +726,22 @@ var IconGrid = GObject.registerClass({
this.add_actor(item.actor);
}
moveItem(item, newPosition) {
if (!this.contains(item.actor)) {
log('Cannot move item not contained by the IconGrid');
return;
}
let children = this.get_children();
let visibleChildren = children.filter(c => c.is_visible());
let visibleChildAtPosition = visibleChildren[newPosition];
let realPosition = children.indexOf(visibleChildAtPosition);
this.set_child_at_index(item.actor, realPosition);
return realPosition;
}
removeItem(item) {
this.remove_child(item.actor);
}
@@ -755,17 +823,237 @@ var IconGrid = GObject.registerClass({
this._updateSpacingForSize(availWidth, availHeight);
}
Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
if (!this._updateIconSizesLaterId)
this._updateIconSizesLaterId = Meta.later_add(Meta.LaterType.BEFORE_REDRAW,
this._updateIconSizes.bind(this));
}
// Note that this is ICON_SIZE as used by BaseIcon, not elsewhere in IconGrid; it's a bit messed up
_updateIconSizes() {
this._updateIconSizesLaterId = 0;
let scale = Math.min(this._fixedHItemSize, this._fixedVItemSize) / Math.max(this._hItemSize, this._vItemSize);
let newIconSize = Math.floor(ICON_SIZE * scale);
for (let i in this._items) {
this._items[i].icon.setIconSize(newIconSize);
}
return GLib.SOURCE_REMOVE;
}
// Drag n' Drop methods
nudgeItemsAtIndex(index, dragLocation) {
// No nudging when the cursor is in an empty area
if (dragLocation == DragLocation.EMPTY_AREA || dragLocation == DragLocation.ON_ICON)
return;
let children = this.get_children().filter(c => c.is_visible());
let nudgeIndex = index;
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
if (dragLocation != DragLocation.START_EDGE) {
let leftItem = children[nudgeIndex - 1];
let offset = rtl ? Math.floor(this._hItemSize * NUDGE_FACTOR) : Math.floor(-this._hItemSize * NUDGE_FACTOR);
this._animateNudge(leftItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset);
}
// Nudge the icon to the right if we are the first item or not at the
// end of row
if (dragLocation != DragLocation.END_EDGE) {
let rightItem = children[nudgeIndex];
let offset = rtl ? Math.floor(-this._hItemSize * NUDGE_FACTOR) : Math.floor(this._hItemSize * NUDGE_FACTOR);
this._animateNudge(rightItem, NUDGE_ANIMATION_TYPE, NUDGE_DURATION, offset);
}
}
removeNudges() {
let children = this.get_children().filter(c => c.is_visible());
for (let index = 0; index < children.length; index++) {
this._animateNudge(children[index],
NUDGE_RETURN_ANIMATION_TYPE,
NUDGE_RETURN_DURATION,
0);
}
}
_animateNudge(item, animationType, duration, offset) {
if (!item)
return;
item.save_easing_state();
item.set_easing_mode(animationType);
item.set_easing_duration(duration);
item.translation_x = offset;
item.restore_easing_state();
}
// This function is overriden by the PaginatedIconGrid subclass so we can
// take into account the extra space when dragging from a folder
_calculateDndRow(y) {
let rowHeight = this._getVItemSize() + this._getSpacing();
return Math.floor(y / rowHeight);
}
// Returns the drop point index or -1 if we can't drop there
canDropAt(x, y) {
// This is an complex calculation, but in essence, we divide the grid
// as:
//
// left empty space
// | left padding right padding
// | | width without padding |
// +--------+---+---------------------------------------+-----+
// | | | | | | | |
// | | | | | | | |
// | | |--------+-----------+----------+-------| |
// | | | | | | | |
// | | | | | | | |
// | | |--------+-----------+----------+-------| |
// | | | | | | | |
// | | | | | | | |
// | | |--------+-----------+----------+-------| |
// | | | | | | | |
// | | | | | | | |
// +--------+---+---------------------------------------+-----+
//
// The left empty space is immediately discarded, and ignored in all
// calculations.
//
// The width (with paddings) is used to determine if we're dragging
// over the left or right padding, and which column is being dragged
// on.
//
// Finally, the width without padding is used to figure out where in
// the icon (start edge, end edge, on it, etc) the cursor is.
let [nColumns, usedWidth] = this._computeLayout(this.width);
let leftEmptySpace;
switch (this._xAlign) {
case St.Align.START:
leftEmptySpace = 0;
break;
case St.Align.MIDDLE:
leftEmptySpace = Math.floor((this.width - usedWidth) / 2);
break;
case St.Align.END:
leftEmptySpace = availWidth - usedWidth;
}
x -= leftEmptySpace;
y -= this.topPadding;
let row = this._calculateDndRow(y);
// Correct sx to handle the left padding to correctly calculate
// the column
let rtl = (Clutter.get_default_text_direction() == Clutter.TextDirection.RTL);
let gridX = x - this.leftPadding;
let widthWithoutPadding = usedWidth - this.leftPadding - this.rightPadding;
let columnWidth = widthWithoutPadding / nColumns;
let column;
if (x < this.leftPadding)
column = 0;
else if (x > usedWidth - this.rightPadding)
column = nColumns - 1;
else
column = Math.floor(gridX / columnWidth);
let isFirstIcon = column == 0;
let isLastIcon = column == nColumns - 1;
// If we're outside of the grid, we are in an invalid drop location
if (x < 0 || x > usedWidth)
return [-1, DragLocation.DEFAULT];
let children = this.get_children().filter(c => c.is_visible());
let childIndex = Math.min((row * nColumns) + column, children.length);
// If we're above the grid vertically, we are in an invalid
// drop location
if (childIndex < 0)
return [-1, DragLocation.DEFAULT];
// If we're past the last visible element in the grid,
// we might be allowed to drop there.
if (childIndex >= children.length)
return [children.length, DragLocation.EMPTY_AREA];
let child = children[childIndex];
let [childMinWidth, childMinHeight, childNaturalWidth, childNaturalHeight] = child.get_preferred_size();
// This is the width of the cell that contains the icon
// (excluding spacing between cells)
let childIconWidth = Math.max(this._getHItemSize(), childNaturalWidth);
// Calculate the original position of the child icon (prior to nudging)
let childX;
if (rtl)
childX = widthWithoutPadding - (column * columnWidth) - childIconWidth;
else
childX = column * columnWidth;
let iconLeftX = childX + LEFT_DIVIDER_LEEWAY;
let iconRightX = childX + childIconWidth - RIGHT_DIVIDER_LEEWAY
let dropIndex;
let dragLocation;
x -= this.leftPadding;
if (x < iconLeftX) {
// We are to the left of the icon target
if (isFirstIcon || x < 0) {
// We are before the leftmost icon on the grid
if (rtl) {
dropIndex = childIndex + 1;
dragLocation = DragLocation.END_EDGE;
} else {
dropIndex = childIndex;
dragLocation = DragLocation.START_EDGE;
}
} else {
// We are between the previous icon (next in RTL) and this one
if (rtl)
dropIndex = childIndex + 1;
else
dropIndex = childIndex;
dragLocation = DragLocation.DEFAULT;
}
} else if (x >= iconRightX) {
// We are to the right of the icon target
if (childIndex >= children.length) {
// We are beyond the last valid icon
// (to the right of the app store / trash can, if present)
dropIndex = -1;
dragLocation = DragLocation.DEFAULT;
} else if (isLastIcon || x >= widthWithoutPadding) {
// We are beyond the rightmost icon on the grid
if (rtl) {
dropIndex = childIndex;
dragLocation = DragLocation.START_EDGE;
} else {
dropIndex = childIndex + 1;
dragLocation = DragLocation.END_EDGE;
}
} else {
// We are between this icon and the next one (previous in RTL)
if (rtl)
dropIndex = childIndex;
else
dropIndex = childIndex + 1;
dragLocation = DragLocation.DEFAULT;
}
} else {
// We are over the icon target area
dropIndex = childIndex;
dragLocation = DragLocation.ON_ICON;
}
return [dropIndex, dragLocation];
}
});
@@ -782,7 +1070,7 @@ var PaginatedIconGrid = GObject.registerClass({
this._childrenPerPage = 0;
}
vfunc_get_preferred_height(forWidth) {
vfunc_get_preferred_height(_forWidth) {
let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
return [height, height];
}
@@ -819,10 +1107,21 @@ var PaginatedIconGrid = GObject.registerClass({
let x = box.x1 + leftEmptySpace + this.leftPadding;
let y = box.y1 + this.topPadding;
let columnIndex = 0;
let nChanged = 0;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
// Figure out how much delay to apply
if (!childBox.equal(children[i].get_allocation_box()))
nChanged++;
children[i].save_easing_state();
children[i].set_easing_mode(Clutter.AnimationMode.EASE_OUT_QUAD);
children[i].set_easing_delay(ICON_POSITION_DELAY * nChanged);
children[i].allocate(childBox, flags);
children[i].restore_easing_state();
children[i].show();
columnIndex++;
@@ -841,6 +1140,23 @@ var PaginatedIconGrid = GObject.registerClass({
}
// Overridden from IconGrid
_calculateDndRow(y) {
let row = super._calculateDndRow(y);
// If there's no extra space, just return the current value and maintain
// the same behavior when without a folder opened.
if (!this._extraSpaceData)
return row;
let [ baseRow, nRowsUp, nRowsDown ] = this._extraSpaceData;
let newRow = row + nRowsUp;
if (row > baseRow)
newRow -= nRowsDown;
return newRow;
}
_getChildrenToAnimate() {
let children = this._getVisibleChildren();
let firstIndex = this._childrenPerPage * this.currentPage;
@@ -850,7 +1166,7 @@ var PaginatedIconGrid = GObject.registerClass({
}
_computePages(availWidthPerPage, availHeightPerPage) {
let [nColumns, usedWidth] = this._computeLayout(availWidthPerPage);
let [nColumns, usedWidth_] = this._computeLayout(availWidthPerPage);
let nRows;
let children = this._getVisibleChildren();
if (nColumns > 0)

View File

@@ -1,3 +1,4 @@
/* exported InhibitShortcutsDialog */
const { Clutter, Gio, GLib, GObject, Gtk, Meta, Shell } = imports.gi;
const Dialog = imports.ui.dialog;
@@ -139,7 +140,7 @@ var InhibitShortcutsDialog = GObject.registerClass({
return;
}
let [permissions, data] = res;
let [permissions] = res;
if (permissions[appId] === undefined) // Not found
this._dialog.open();
else if (permissions[appId] == GRANTED)

View File

@@ -1,3 +1,4 @@
/* exported KbdA11yDialog */
const { Clutter, Gio, GObject } = imports.gi;
const Dialog = imports.ui.dialog;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Keyboard */
const { Clutter, Gio, GLib, GObject, Meta, St } = imports.gi;
const Signals = imports.signals;
@@ -100,7 +101,7 @@ class KeyContainer extends St.Widget {
this._rows = [];
}
appendRow(length) {
appendRow() {
this._currentRow++;
this._currentCol = 0;
@@ -474,7 +475,7 @@ var KeyboardModel = class {
_loadModel(groupName) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/%s.json'.format(groupName));
let [success, contents] = file.load_contents(null);
let [success_, contents] = file.load_contents(null);
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
@@ -662,7 +663,7 @@ var EmojiPager = class EmojiPager {
}
_onPan(action) {
let [dist, dx, dy] = action.get_motion_delta(0);
let [dist_, dx, dy_] = action.get_motion_delta(0);
this.delta = this.delta + dx;
if (this._currentKey != null) {
@@ -904,7 +905,7 @@ var EmojiSelection = class EmojiSelection {
_populateSections() {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/osk-layouts/emoji.json');
let [success, contents] = file.load_contents(null);
let [success_, contents] = file.load_contents(null);
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
@@ -1171,7 +1172,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', () => this.hide());
this._emojiSelection.connect('emoji-selected', (selection, emoji) => {
this._keyboardController.commitString(emoji);
});
@@ -1282,7 +1283,7 @@ var Keyboard = class Keyboard {
}
}
});
button.connect('released', (actor, keyval, str) => {
button.connect('released', (actor, keyval, _str) => {
if (keyval != 0) {
if (button._keyvalPress)
this._keyboardController.keyvalRelease(keyval);
@@ -1467,7 +1468,7 @@ var Keyboard = class Keyboard {
this._setActiveLayer(0);
}
_onKeyboardGroupsChanged(keyboard) {
_onKeyboardGroupsChanged() {
let nonGroupActors = [this._emojiSelection.actor, this._keypad.actor];
this._aspectContainer.get_children().filter(c => !nonGroupActors.includes(c)).forEach(c => {
c.destroy();
@@ -1729,7 +1730,7 @@ var KeyboardController = class {
this.emit('groups-changed');
}
_onSourceChanged(inputSourceManager, oldSource) {
_onSourceChanged(inputSourceManager, _oldSource) {
let source = inputSourceManager.currentSource;
this._currentSource = source;
this.emit('active-group', source.id);

View File

@@ -1,6 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported MonitorConstraint, LayoutManager */
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;
@@ -80,10 +81,12 @@ var MonitorConstraint = GObject.registerClass({
this.notify('index');
}
// eslint-disable-next-line camelcase
get work_area() {
return this._workArea;
}
// eslint-disable-next-line camelcase
set work_area(v) {
if (v == this._workArea)
return;
@@ -165,12 +168,12 @@ var Monitor = class Monitor {
const UiActor = GObject.registerClass(
class UiActor extends St.Widget {
vfunc_get_preferred_width (forHeight) {
vfunc_get_preferred_width (_forHeight) {
let width = global.stage.width;
return [width, width];
}
vfunc_get_preferred_height (forWidth) {
vfunc_get_preferred_height (_forWidth) {
let height = global.stage.height;
return [height, height];
}
@@ -274,6 +277,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',
@@ -377,6 +387,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
@@ -829,7 +844,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) {
@@ -839,8 +854,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) {
@@ -1220,7 +1233,7 @@ var HotCorner = class HotCorner {
}
}
handleDragOver(source, actor, x, y, time) {
handleDragOver(source, _actor, _x, _y, _time) {
if (source != Main.xdndHandler)
return DND.DragMotionResult.CONTINUE;
@@ -1321,7 +1334,7 @@ var PressureBarrier = class PressureBarrier {
let threshold = this._lastTime - this._timeout;
while (i < this._barrierEvents.length) {
let [time, distance] = this._barrierEvents[i];
let [time, distance_] = this._barrierEvents[i];
if (time >= threshold)
break;
i++;
@@ -1330,14 +1343,14 @@ var PressureBarrier = class PressureBarrier {
let firstNewEvent = i;
for (i = 0; i < firstNewEvent; i++) {
let [time, distance] = this._barrierEvents[i];
let [time_, distance] = this._barrierEvents[i];
this._currentPressure -= distance;
}
this._barrierEvents = this._barrierEvents.slice(firstNewEvent);
}
_onBarrierLeft(barrier, event) {
_onBarrierLeft(barrier, _event) {
barrier._isHit = false;
if (this._barriers.every(b => !b._isHit)) {
this._reset();

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Lightbox */
const { Clutter, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -23,8 +24,8 @@ t = clamp(t, 0.0, 1.0);\n\
float pixel_brightness = mix(1.0, 1.0 - vignette_sharpness, t);\n\
cogl_color_out.a = cogl_color_out.a * (1 - pixel_brightness * brightness);';
var RadialShaderQuad = GObject.registerClass(
class RadialShaderQuad extends Shell.GLSLQuad {
var RadialShaderEffect = GObject.registerClass(
class RadialShaderEffect extends Shell.GLSLEffect {
_init(params) {
super._init(params);
@@ -98,16 +99,13 @@ var Lightbox = class Lightbox {
this._children = container.get_children();
this._fadeFactor = params.fadeFactor;
this._radialEffect = Clutter.feature_available(Clutter.FeatureFlags.SHADERS_GLSL) && params.radialEffect;
this.actor = new St.Bin({ reactive: params.inhibitEvents });
if (this._radialEffect)
this.actor = new RadialShaderQuad({ x: 0,
y: 0,
reactive: params.inhibitEvents });
this.actor.add_effect(new RadialShaderEffect({ name: 'radial' }));
else
this.actor = new St.Bin({ x: 0,
y: 0,
opacity: 0,
style_class: 'lightbox',
reactive: params.inhibitEvents });
this.actor.set({ opacity: 0, style_class: 'lightbox' });
container.add_actor(this.actor);
this.actor.raise_top();
@@ -156,9 +154,10 @@ var Lightbox = class Lightbox {
show(fadeInTime) {
fadeInTime = fadeInTime || 0;
Tweener.removeTweens(this.actor);
if (this._radialEffect) {
Tweener.addTween(this.actor,
let effect = this.actor.get_effect('radial');
Tweener.removeTweens(effect);
Tweener.addTween(effect,
{ brightness: VIGNETTE_BRIGHTNESS,
vignetteSharpness: VIGNETTE_SHARPNESS,
time: fadeInTime,
@@ -169,6 +168,7 @@ var Lightbox = class Lightbox {
}
});
} else {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 255 * this._fadeFactor,
time: fadeInTime,
@@ -187,9 +187,11 @@ var Lightbox = class Lightbox {
fadeOutTime = fadeOutTime || 0;
this.shown = false;
Tweener.removeTweens(this.actor);
if (this._radialEffect) {
Tweener.addTween(this.actor,
let effect = this.actor.get_effect('radial');
Tweener.removeTweens(effect);
Tweener.addTween(effect,
{ brightness: 1.0,
vignetteSharpness: 0.0,
opacity: 0,
@@ -200,6 +202,7 @@ var Lightbox = class Lightbox {
}
});
} else {
Tweener.removeTweens(this.actor);
Tweener.addTween(this.actor,
{ opacity: 0,
time: fadeOutTime,

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LocatePointer */
const { Gio } = imports.gi;
const Ripples = imports.ui.ripples;
@@ -18,7 +19,7 @@ var LocatePointer = class {
if (!this._settings.get_boolean(LOCATE_POINTER_KEY))
return;
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
this._ripples.playAnimation(x, y);
}
};

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported LookingGlass */
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
@@ -7,13 +8,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 */
@@ -266,7 +268,7 @@ var ObjLink = class ObjLink {
this._lookingGlass = lookingGlass;
}
_onClicked(link) {
_onClicked() {
this._lookingGlass.inspectObject(this._obj, this.actor);
}
};
@@ -518,7 +520,7 @@ var Inspector = GObject.registerClass({
let primary = Main.layoutManager.primaryMonitor;
let [minWidth, minHeight, natWidth, natHeight] =
let [, , natWidth, natHeight] =
this._eventHandler.get_preferred_size();
let childBox = new Clutter.ActorBox();
@@ -623,15 +625,16 @@ var Extensions = class Extensions {
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)
@@ -688,16 +691,16 @@ var Extensions = class Extensions {
_stateToString(extensionState) {
switch (extensionState) {
case ExtensionSystem.ExtensionState.ENABLED:
case ExtensionState.ENABLED:
return _("Enabled");
case ExtensionSystem.ExtensionState.DISABLED:
case ExtensionSystem.ExtensionState.INITIALIZED:
case ExtensionState.DISABLED:
case ExtensionState.INITIALIZED:
return _("Disabled");
case ExtensionSystem.ExtensionState.ERROR:
case ExtensionState.ERROR:
return _("Error");
case ExtensionSystem.ExtensionState.OUT_OF_DATE:
case ExtensionState.OUT_OF_DATE:
return _("Out of date");
case ExtensionSystem.ExtensionState.DOWNLOADING:
case ExtensionState.DOWNLOADING:
return _("Downloading");
}
return 'Unknown'; // Not translated, shouldn't appear
@@ -854,7 +857,7 @@ var LookingGlass = class LookingGlass {
this._extensions = new Extensions(this);
notebook.appendPage('Extensions', this._extensions.actor);
this._entry.clutter_text.connect('activate', (o, e) => {
this._entry.clutter_text.connect('activate', (o, _e) => {
// Hide any completions we are currently showing
this._hideCompletions();
@@ -940,15 +943,16 @@ var LookingGlass = class LookingGlass {
// Setting the height to -1 allows us to get its actual preferred height rather than
// whatever was last given in set_height by Tweener.
this._completionActor.set_height(-1);
let [minHeight, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width());
let [, naturalHeight] = this._completionActor.get_preferred_height(this._resultsArea.get_width());
// Don't reanimate if we are already visible
if (this._completionActor.visible) {
this._completionActor.height = naturalHeight;
} else {
let settings = St.Settings.get();
this._completionActor.show();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor,
transition: 'easeOutQuad',
height: naturalHeight,
opacity: 255
@@ -958,8 +962,9 @@ var LookingGlass = class LookingGlass {
_hideCompletions() {
if (this._completionActor) {
let settings = St.Settings.get();
Tweener.removeTweens(this._completionActor);
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / St.get_slow_down_factor(),
Tweener.addTween(this._completionActor, { time: AUTO_COMPLETE_SHOW_COMPLETION_ANIMATION_DURATION / settings.slow_down_factor,
transition: 'easeOutQuad',
height: 0,
opacity: 0,
@@ -1009,7 +1014,10 @@ var LookingGlass = class LookingGlass {
}
_queueResize() {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => this._resize());
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._resize();
return GLib.SOURCE_REMOVE;
});
}
_resize() {
@@ -1076,7 +1084,8 @@ var LookingGlass = class LookingGlass {
// We inverse compensate for the slow-down so you can change the factor
// through LookingGlass without long waits.
Tweener.addTween(this.actor, { time: 0.5 / St.get_slow_down_factor(),
let settings = St.Settings.get();
Tweener.addTween(this.actor, { time: 0.5 / settings.slow_down_factor,
transition: 'easeOutQuad',
y: this._targetY
});
@@ -1095,7 +1104,8 @@ var LookingGlass = class LookingGlass {
Main.popModal(this._entry);
Tweener.addTween(this.actor, { time: Math.min(0.5 / St.get_slow_down_factor(), 0.5),
let settings = St.Settings.get();
Tweener.addTween(this.actor, { time: Math.min(0.5 / settings.slow_down_factor, 0.5),
transition: 'easeOutQuad',
y: this._hiddenY,
onComplete: () => {

View File

@@ -107,8 +107,7 @@ var Magnifier = class Magnifier {
// Create the first ZoomRegion and initialize it according to the
// magnification settings.
let mask;
[this.xMouse, this.yMouse, mask] = global.get_pointer();
[this.xMouse, this.yMouse] = global.get_pointer();
let aZoomRegion = new ZoomRegion(this, this._cursorRoot);
this._zoomRegions.push(aZoomRegion);
@@ -148,7 +147,7 @@ var Magnifier = class Magnifier {
setActive(activate) {
let isActive = this.isActive();
this._zoomRegions.forEach((zoomRegion, index, array) => {
this._zoomRegions.forEach(zoomRegion => {
zoomRegion.setActive(activate);
});
@@ -227,14 +226,14 @@ var Magnifier = class Magnifier {
* @return true.
*/
scrollToMousePos() {
let [xMouse, yMouse, mask] = global.get_pointer();
let [xMouse, yMouse] = global.get_pointer();
if (xMouse != this.xMouse || yMouse != this.yMouse) {
this.xMouse = xMouse;
this.yMouse = yMouse;
let sysMouseOverAny = false;
this._zoomRegions.forEach((zoomRegion, index, array) => {
this._zoomRegions.forEach(zoomRegion => {
if (zoomRegion.scrollToMousePos())
sysMouseOverAny = true;
});
@@ -332,7 +331,7 @@ var Magnifier = class Magnifier {
this.setCrosshairsClip(clip);
let theCrossHairs = this._crossHairs;
this._zoomRegions.forEach ((zoomRegion, index, array) => {
this._zoomRegions.forEach (zoomRegion => {
zoomRegion.addCrosshairs(theCrossHairs);
});
}
@@ -360,7 +359,7 @@ var Magnifier = class Magnifier {
*/
setCrosshairsColor(color) {
if (this._crossHairs) {
let [res, clutterColor] = Clutter.Color.from_string(color);
let [res_, clutterColor] = Clutter.Color.from_string(color);
this._crossHairs.setColor(clutterColor);
}
}
@@ -1515,7 +1514,7 @@ var ZoomRegion = class ZoomRegion {
}
_centerFromPointProportional(xPoint, yPoint) {
let [xRoi, yRoi, widthRoi, heightRoi] = this.getROI();
let [xRoi_, yRoi_, widthRoi, heightRoi] = this.getROI();
let halfScreenWidth = global.screen_width / 2;
let halfScreenHeight = global.screen_height / 2;
// We want to pad with a constant distance after zooming, so divide

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ShellMagnifier */
const Gio = imports.gi.Gio;
const Main = imports.ui.main;
@@ -124,7 +125,7 @@ var ShellMagnifier = class ShellMagnifier {
let zoomRegions = Main.magnifier.getZoomRegions();
let objectPaths = [];
let thoseZoomers = this._zoomers;
zoomRegions.forEach ((aZoomRegion, index, array) => {
zoomRegions.forEach (aZoomRegion => {
let found = false;
for (let objectPath in thoseZoomers) {
let proxyAndZoomRegion = thoseZoomers[objectPath];

View File

@@ -1,4 +1,12 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported componentManager, notificationDaemon, windowAttentionHandler,
ctrlAltTabManager, padOsdService, osdWindowManager,
osdMonitorLabeler, shellMountOpDBusService, shellDBusService,
shellAccessDialogDBusService, shellAudioSelectionDBusService,
screenSaverDBus, screencastService, uiGroup, magnifier,
xdndHandler, keyboard, kbdA11yDialog, introspectService,
start, pushModal, popModal, activateWindow, createLookingGlass,
initializeDeferredWork, getThemeStylesheet, setThemeStylesheet */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -46,6 +54,7 @@ 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;
@@ -226,7 +235,8 @@ function _initializeUI() {
_startDate = new Date();
ExtensionDownloader.init();
ExtensionSystem.init();
extensionManager = new ExtensionSystem.ExtensionManager();
extensionManager.init();
if (sessionMode.isGreeter && screenShield) {
layoutManager.connect('startup-prepared', () => {
@@ -656,7 +666,7 @@ function _queueBeforeRedraw(workId) {
*
* Returns: A string work identifier
*/
function initializeDeferredWork(actor, callback, props) {
function initializeDeferredWork(actor, callback) {
// Turn into a string so we can use as an object property
let workId = `${(++_deferredWorkSequence)}`;
_deferredWorkData[workId] = { 'actor': actor,

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';
@@ -132,12 +130,12 @@ var URLHighlighter = class URLHighlighter {
}
_findUrlAtPos(event) {
let success;
let success_;
let [x, y] = event.get_coords();
[success, x, y] = this.actor.transform_stage_point(x, y);
[success_, x, y] = this.actor.transform_stage_point(x, y);
let findPos = -1;
for (let i = 0; i < this.actor.clutter_text.text.length; i++) {
let [success, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
let [success_, px, py, lineHeight] = this.actor.clutter_text.position_to_coords(i);
if (py > y || py + lineHeight < y || x < px)
continue;
findPos = i;

View File

@@ -1,4 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationPolicy, NotificationGenericPolicy,
NotificationApplicationPolicy, Source, SourceActor, SourceActorWithLabel,
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -473,9 +476,7 @@ var Notification = class Notification {
this.destroy();
}
destroy(reason) {
if (!reason)
reason = NotificationDestroyedReason.DISMISSED;
destroy(reason = NotificationDestroyedReason.DISMISSED) {
this.emit('destroy', reason);
}
};
@@ -652,7 +653,7 @@ class SourceActorWithLabel extends SourceActor {
let childBox = new Clutter.ActorBox();
let [minWidth, minHeight, naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let [, , naturalWidth, naturalHeight] = this._counterBin.get_preferred_size();
let direction = this.get_text_direction();
if (direction == Clutter.TextDirection.LTR) {
@@ -829,7 +830,7 @@ Signals.addSignalMethods(Source.prototype);
var MessageTray = class MessageTray {
constructor() {
this._presence = new GnomeSession.Presence((proxy, error) => {
this._presence = new GnomeSession.Presence((proxy, _error) => {
this._onStatusChanged(proxy.status);
});
this._busy = false;
@@ -1129,7 +1130,7 @@ var MessageTray = class MessageTray {
// this._onNotificationLeftTimeout() to determine if the mouse has moved far enough during the initial timeout for us
// to consider that the user intended to leave the tray and therefore hide the tray. If the mouse is still
// close to its previous position, we extend the timeout once.
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
this._notificationLeftMouseX = x;
this._notificationLeftMouseY = y;
@@ -1158,7 +1159,7 @@ var MessageTray = class MessageTray {
}
_onNotificationLeftTimeout() {
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
// We extend the timeout once if the mouse moved no further than MOUSE_LEFT_ACTOR_THRESHOLD to either side.
if (this._notificationLeftMouseX > -1 &&
y < this._notificationLeftMouseY + MOUSE_LEFT_ACTOR_THRESHOLD &&
@@ -1310,7 +1311,7 @@ var MessageTray = class MessageTray {
Meta.disable_unredirect_for_display(global.display);
this._updateShowingNotification();
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
// We save the position of the mouse at the time when we started showing the notification
// in order to determine if the notification popped up under it. We make that check if
// the user starts moving the mouse and _onNotificationHoverChanged() gets called. We don't
@@ -1380,7 +1381,7 @@ var MessageTray = class MessageTray {
}
_notificationTimeout() {
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
if (y < this._lastSeenMouseY - 10 && !this._notificationHovered) {
// The mouse is moving towards the notification, so don't
// hide it yet. (We just create a new timeout (and destroy

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ModalDialog */
const { Atk, Clutter, GObject, Shell, St } = imports.gi;

View File

@@ -1,3 +1,4 @@
/* exported MediaSection */
const { Gio, Shell, St } = imports.gi;
const Signals = imports.signals;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -64,7 +65,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
_imageForNotificationData(hints) {
if (hints['image-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = hints['image-data'];
bitsPerSample, nChannels_, data] = hints['image-data'];
return Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
} else if (hints['image-path']) {
@@ -259,7 +260,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
}
_notifyForSource(source, ndata) {
let [id, icon, summary, body, actions, hints, notification] =
let [id_, icon, summary, body, actions, hints, notification] =
[ndata.id, ndata.icon, ndata.summary, ndata.body,
ndata.actions, ndata.hints, ndata.notification];

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdMonitorLabeler */
const { Clutter, Gio, Meta, St } = imports.gi;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported OsdWindowManager */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -12,39 +13,6 @@ var HIDE_TIMEOUT = 1500;
var FADE_TIME = 0.1;
var LEVEL_ANIMATION_TIME = 0.1;
var LevelBar = class extends BarLevel.BarLevel {
constructor() {
super(0, { styleClass: 'level' });
this._level = 0;
this._maxLevel = 100;
this.actor.accessible_name = _("Volume");
this.actor.connect('notify::width', () => this.level = this.level);
}
get level() {
return this._level;
}
set level(value) {
this._level = Math.max(0, Math.min(value, this._maxLevel));
this.setValue(this._level / 100);
}
get maxLevel() {
return this._maxLevel;
}
set maxLevel(value) {
this._maxLevel = Math.max(100, value);
this.setMaximumValue(this._maxLevel / 100);
}
};
var OsdWindowConstraint = GObject.registerClass(
class OsdWindowConstraint extends Clutter.Constraint {
_init(props) {
@@ -98,7 +66,7 @@ var OsdWindow = class {
this._label = new St.Label();
this._box.add(this._label);
this._level = new LevelBar();
this._level = new BarLevel.BarLevel(0, { styleClass: 'level' });
this._box.add(this._level.actor);
this._hideTimeoutId = 0;
@@ -138,23 +106,21 @@ var OsdWindow = class {
this._label.text = label;
}
setLevel(level) {
this._level.actor.visible = (level != undefined);
if (level != undefined) {
setLevel(value) {
this._level.actor.visible = (value != undefined);
if (value != undefined) {
if (this.actor.visible)
Tweener.addTween(this._level,
{ level: level,
{ value: value,
time: LEVEL_ANIMATION_TIME,
transition: 'easeOutQuad' });
else
this._level.level = level;
this._level.value = value;
}
}
setMaxLevel(maxLevel) {
if (maxLevel === undefined)
maxLevel = 100;
this._level.maxLevel = maxLevel;
setMaxLevel(maxLevel = 1) {
this._level.maximum_value = maxLevel;
}
show() {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
@@ -386,16 +387,16 @@ var Overview = class {
this.emit('windows-restacked', stackIndices);
}
beginItemDrag(source) {
beginItemDrag(_source) {
this.emit('item-drag-begin');
this._inItemDrag = true;
}
cancelledItemDrag(source) {
cancelledItemDrag(_source) {
this.emit('item-drag-cancelled');
}
endItemDrag(source) {
endItemDrag(_source) {
if (!this._inItemDrag)
return;
this.emit('item-drag-end');

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported ControlsManager */
const { Clutter, GObject, Meta, St } = imports.gi;
@@ -423,17 +424,6 @@ var ControlsManager = class {
layout.connect('allocation-changed', this._updateWorkspacesGeometry.bind(this));
Main.overview.connect('showing', this._updateSpacerVisibility.bind(this));
Main.overview.connect('item-drag-begin', () => {
let activePage = this.viewSelector.getActivePage();
if (activePage != ViewSelector.ViewPage.WINDOWS)
this.viewSelector.fadeHalf();
});
Main.overview.connect('item-drag-end', () => {
this.viewSelector.fadeIn();
});
Main.overview.connect('item-drag-cancelled', () => {
this.viewSelector.fadeIn();
});
}
_updateWorkspacesGeometry() {

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PadOsdService */
const { Atk, Clutter, GDesktopEnums, Gio,
GLib, GObject, Gtk, Meta, Rsvg, St } = imports.gi;
@@ -295,7 +296,7 @@ var PadDiagram = GObject.registerClass({
}, class PadDiagram extends St.DrawingArea {
_init(params) {
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/pad-osd.css');
let [success, css, etag] = file.load_contents(null);
let [success_, css] = file.load_contents(null);
if (css instanceof Uint8Array)
css = imports.byteArray.toString(css);
this._curEdited = null;
@@ -306,10 +307,12 @@ var PadDiagram = GObject.registerClass({
super._init(params);
}
// eslint-disable-next-line camelcase
get left_handed() {
return this._leftHanded;
}
// eslint-disable-next-line camelcase
set left_handed(leftHanded) {
this._leftHanded = leftHanded;
}
@@ -328,10 +331,12 @@ var PadDiagram = GObject.registerClass({
this._handle = this._composeStyledDiagram();
}
// eslint-disable-next-line camelcase
get editor_actor() {
return this._editorActor;
}
// eslint-disable-next-line camelcase
set editor_actor(actor) {
actor.hide();
this._editorActor = actor;
@@ -396,8 +401,8 @@ var PadDiagram = GObject.registerClass({
}
_allocateChild(child, x, y, direction) {
let [prefHeight, natHeight] = child.get_preferred_height(-1);
let [prefWidth, natWidth] = child.get_preferred_width(natHeight);
let [, natHeight] = child.get_preferred_height(-1);
let [, natWidth] = child.get_preferred_width(natHeight);
let childBox = new Clutter.ActorBox();
if (direction == LTR) {
@@ -419,13 +424,13 @@ var PadDiagram = GObject.registerClass({
for (let i = 0; i < this._labels.length; i++) {
let [label, action, idx, dir] = this._labels[i];
let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(label, x, y, arrangement);
}
if (this._editorActor && this._curEdited) {
let [label, action, idx, dir] = this._curEdited;
let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
let [label_, action, idx, dir] = this._curEdited;
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(this._editorActor, x, y, arrangement);
}
}
@@ -561,7 +566,7 @@ var PadDiagram = GObject.registerClass({
if (str != null) {
label.set_text(str);
let [found, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
let [found_, x, y, arrangement] = this.getLabelCoords(action, idx, dir);
this._allocateChild(label, x, y, arrangement);
}
label.show();
@@ -789,13 +794,13 @@ var PadOsd = class {
} else if (event.get_source_device() == this.padDevice &&
event.type() == Clutter.EventType.PAD_STRIP) {
if (this._editionMode) {
let [retval, number, mode] = event.get_pad_event_details();
let [retval_, number, mode] = event.get_pad_event_details();
this._startStripActionEdition(number, UP, mode);
}
} else if (event.get_source_device() == this.padDevice &&
event.type() == Clutter.EventType.PAD_RING) {
if (this._editionMode) {
let [retval, number, mode] = event.get_pad_event_details();
let [retval_, number, mode] = event.get_pad_event_details();
this._startRingActionEdition(number, CCW, mode);
}
}

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PageIndicators, AnimatedPageIndicators */
const { Clutter, GObject, St } = imports.gi;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Panel */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
@@ -19,8 +20,6 @@ var APP_MENU_ICON_MARGIN = 0;
var BUTTON_DND_ACTIVATION_TIMEOUT = 250;
var SPINNER_ANIMATION_TIME = 1.0;
// To make sure the panel corners blend nicely with the panel,
// we draw background and borders the same way, e.g. drawing
// them as filled shapes from the outside inwards instead of
@@ -203,7 +202,6 @@ var AppMenuButton = GObject.registerClass({
this._busyNotifyId = 0;
let bin = new St.Bin({ name: 'appMenu' });
bin.connect('style-changed', this._onStyleChanged.bind(this));
this.add_actor(bin);
this.bind_property("reactive", this, "can-focus", 0);
@@ -238,9 +236,8 @@ var AppMenuButton = GObject.registerClass({
this._overviewHidingId = Main.overview.connect('hiding', this._sync.bind(this));
this._overviewShowingId = Main.overview.connect('showing', this._sync.bind(this));
this._stop = true;
this._spinner = null;
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
this._container.add_actor(this._spinner.actor);
let menu = new AppMenu(this);
this.setMenu(menu);
@@ -288,17 +285,6 @@ var AppMenuButton = GObject.registerClass({
} });
}
_onStyleChanged(actor) {
let node = actor.get_theme_node();
let [success, icon] = node.lookup_url('spinner-image', false);
if (!success || (this._spinnerIcon && this._spinnerIcon.equal(icon)))
return;
this._spinnerIcon = icon;
this._spinner = new Animation.AnimatedIcon(this._spinnerIcon, PANEL_ICON_SIZE);
this._container.add_actor(this._spinner.actor);
this._spinner.actor.hide();
}
_syncIcon() {
if (!this._targetApp)
return;
@@ -315,34 +301,11 @@ var AppMenuButton = GObject.registerClass({
}
stopAnimation() {
if (this._stop)
return;
this._stop = true;
if (this._spinner == null)
return;
Tweener.addTween(this._spinner.actor,
{ opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: "easeOutQuad",
onComplete: () => {
this._spinner.stop();
this._spinner.actor.opacity = 255;
this._spinner.actor.hide();
}
});
this._spinner.stop();
}
startAnimation() {
this._stop = false;
if (this._spinner == null)
return;
this._spinner.play();
this._spinner.actor.show();
}
_onAppStateChanged(appSys, app) {
@@ -484,14 +447,14 @@ class ActivitiesButton extends PanelMenu.Button {
this._xdndTimeOut = 0;
}
handleDragOver(source, actor, x, y, time) {
handleDragOver(source, _actor, _x, _y, _time) {
if (source != Main.xdndHandler)
return DND.DragMotionResult.CONTINUE;
if (this._xdndTimeOut != 0)
Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, () => {
this._xdndToggleOverview(actor);
this._xdndToggleOverview();
});
GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
@@ -527,8 +490,8 @@ class ActivitiesButton extends PanelMenu.Button {
return Clutter.EVENT_PROPAGATE;
}
_xdndToggleOverview(actor) {
let [x, y, mask] = global.get_pointer();
_xdndToggleOverview() {
let [x, y] = global.get_pointer();
let pickedActor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y);
if (pickedActor == this && Main.overview.shouldToggleByCornerOrButton())
@@ -634,7 +597,7 @@ var PanelCorner = class {
// Synchronize the locate button's pseudo classes with this corner
this._buttonStyleChangedSignalId = button.connect('style-changed',
actor => {
() => {
let pseudoClass = button.get_style_pseudo_class();
this.actor.set_style_pseudo_class(pseudoClass);
});
@@ -706,9 +669,7 @@ var PanelCorner = class {
var AggregateLayout = GObject.registerClass(
class AggregateLayout extends Clutter.BoxLayout {
_init(params) {
if (!params)
params = {};
_init(params = {}) {
params['orientation'] = Clutter.Orientation.VERTICAL;
super._init(params);
@@ -866,7 +827,7 @@ class Panel extends St.Widget {
this._updatePanel();
}
vfunc_get_preferred_width(forHeight) {
vfunc_get_preferred_width(_forHeight) {
let primaryMonitor = Main.layoutManager.primaryMonitor;
if (primaryMonitor)
@@ -881,9 +842,9 @@ class Panel extends St.Widget {
let allocWidth = box.x2 - box.x1;
let allocHeight = box.y2 - box.y1;
let [leftMinWidth, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
let [centerMinWidth, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
let [rightMinWidth, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
let [, leftNaturalWidth] = this._leftBox.get_preferred_width(-1);
let [, centerNaturalWidth] = this._centerBox.get_preferred_width(-1);
let [, rightNaturalWidth] = this._rightBox.get_preferred_width(-1);
let sideWidth, centerWidth;
centerWidth = centerNaturalWidth;
@@ -934,19 +895,18 @@ class Panel extends St.Widget {
}
this._rightBox.allocate(childBox, flags);
let cornerMinWidth, cornerMinHeight;
let cornerWidth, cornerHeight;
[cornerMinWidth, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
[cornerMinHeight, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
[, cornerWidth] = this._leftCorner.actor.get_preferred_width(-1);
[, cornerHeight] = this._leftCorner.actor.get_preferred_height(-1);
childBox.x1 = 0;
childBox.x2 = cornerWidth;
childBox.y1 = allocHeight;
childBox.y2 = allocHeight + cornerHeight;
this._leftCorner.actor.allocate(childBox, flags);
[cornerMinWidth, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
[cornerMinHeight, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
[, cornerWidth] = this._rightCorner.actor.get_preferred_width(-1);
[, cornerHeight] = this._rightCorner.actor.get_preferred_height(-1);
childBox.x1 = allocWidth - cornerWidth;
childBox.x2 = allocWidth;
childBox.y1 = allocHeight;
@@ -1167,7 +1127,7 @@ class Panel extends St.Widget {
}
_onMenuSet(indicator) {
if (!indicator.menu || indicator.menu.hasOwnProperty('_openChangedId'))
if (!indicator.menu || indicator.menu._openChangedId)
return;
indicator.menu._openChangedId = indicator.menu.connect('open-state-changed',

View File

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Button, SystemIndicator */
const { Atk, Clutter, GObject, St } = imports.gi;
const Signals = imports.signals;
@@ -33,7 +34,7 @@ class ButtonBox extends St.Widget {
this._natHPadding = themeNode.get_length('-natural-hpadding');
}
vfunc_get_preferred_width(forHeight) {
vfunc_get_preferred_width(_forHeight) {
let child = this.get_first_child();
let minimumSize, naturalSize;
@@ -48,7 +49,7 @@ class ButtonBox extends St.Widget {
return [minimumSize, naturalSize];
}
vfunc_get_preferred_height(forWidth) {
vfunc_get_preferred_height(_forWidth) {
let child = this.get_first_child();
if (child)
@@ -64,7 +65,7 @@ class ButtonBox extends St.Widget {
if (!child)
return;
let [minWidth, natWidth] = child.get_preferred_width(-1);
let [, natWidth] = child.get_preferred_width(-1);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;

View File

@@ -1,3 +1,4 @@
/* exported PointerA11yTimeout */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Tweener = imports.ui.tweener;
const Main = imports.ui.main;
@@ -85,7 +86,7 @@ var PointerA11yTimeout = class PointerA11yTimeout {
Main.uiGroup.add_actor(pieTimer);
manager.connect('ptr-a11y-timeout-started', (manager, device, type, timeout) => {
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
pieTimer.start(x, y, timeout);
if (type == Clutter.PointerA11yTimeoutType.GESTURE)
global.display.set_cursor(Meta.Cursor.CROSSHAIR);

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported getPointerWatcher */
const { GLib, Meta } = imports.gi;
const Mainloop = imports.mainloop;
@@ -72,13 +73,13 @@ var PointerWatcher = class {
}
}
_onIdleMonitorBecameActive(monitor) {
_onIdleMonitorBecameActive() {
this._idle = false;
this._updatePointer();
this._updateTimeout();
}
_onIdleMonitorBecameIdle(monitor) {
_onIdleMonitorBecameIdle() {
this._idle = true;
this._idleMonitor.add_user_active_watch(this._onIdleMonitorBecameActive.bind(this));
this._updateTimeout();
@@ -108,7 +109,7 @@ var PointerWatcher = class {
}
_updatePointer() {
let [x, y, mods] = global.get_pointer();
let [x, y] = global.get_pointer();
if (this.pointerX == x && this.pointerY == y)
return;

View File

@@ -1,4 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported PopupMenuItem, PopupSeparatorMenuItem, Switch, PopupSwitchMenuItem,
PopupImageMenuItem, PopupMenu, PopupDummyMenu, PopupSubMenu,
PopupMenuSection, PopupSubMenuMenuItem, PopupMenuManager */
const { Atk, Clutter, Gio, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
@@ -122,7 +125,7 @@ var PopupBaseMenuItem = GObject.registerClass({
this._parent = parent;
}
_onButtonPressEvent(actor, event) {
_onButtonPressEvent() {
// This is the CSS active state
this.add_style_pseudo_class('active');
return Clutter.EVENT_PROPAGATE;
@@ -571,7 +574,7 @@ var PopupMenuBase = class {
menuItem.actor.grab_key_focus();
}
});
menuItem._activateId = menuItem.connect_after('activate', (menuItem, event) => {
menuItem._activateId = menuItem.connect_after('activate', (menuItem, _event) => {
this.emit('activate', menuItem);
this.itemActivated(BoxPointer.PopupAnimation.FULL);
});
@@ -958,7 +961,7 @@ var PopupSubMenu = class extends PopupMenuBase {
_needsScrollbar() {
let topMenu = this._getTopMenu();
let [topMinHeight, topNaturalHeight] = topMenu.actor.get_preferred_height(-1);
let [, topNaturalHeight] = topMenu.actor.get_preferred_height(-1);
let topThemeNode = topMenu.actor.get_theme_node();
let topMaxHeight = topThemeNode.get_max_height();
@@ -1008,7 +1011,7 @@ var PopupSubMenu = class extends PopupMenuBase {
let targetAngle = this.actor.text_direction == Clutter.TextDirection.RTL ? -90 : 90;
if (animate) {
let [minHeight, naturalHeight] = this.actor.get_preferred_height(-1);
let [, naturalHeight] = this.actor.get_preferred_height(-1);
this.actor.height = 0;
this.actor._arrowRotation = this._arrow.rotation_angle_z;
Tweener.addTween(this.actor,
@@ -1193,11 +1196,11 @@ class PopupSubMenuMenuItem extends PopupBaseMenuItem {
return super._onKeyPressEvent(actor, event);
}
activate(event) {
activate(_event) {
this._setOpenState(true);
}
_onButtonReleaseEvent(actor) {
_onButtonReleaseEvent() {
// Since we override the parent, we need to manage what the parent does
// with the active style class
this.remove_style_pseudo_class('active');

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported loadRemoteSearchProviders */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
@@ -221,7 +222,7 @@ var RemoteSearchProvider = class {
gicon = Gio.icon_new_for_string(meta['gicon']);
} else if (meta['icon-data']) {
let [width, height, rowStride, hasAlpha,
bitsPerSample, nChannels, data] = meta['icon-data'];
bitsPerSample, nChannels_, data] = meta['icon-data'];
gicon = Shell.util_create_pixbuf_from_data(data, GdkPixbuf.Colorspace.RGB, hasAlpha,
bitsPerSample, width, height, rowStride);
}
@@ -310,7 +311,7 @@ var RemoteSearchProvider = class {
this.proxy.ActivateResultRemote(id);
}
launchSearch(terms) {
launchSearch(_terms) {
// the provider is not compatible with the new version of the interface, launch
// the app itself but warn so we can catch the error in logs
log(`Search provider ${this.appInfo.get_id()} does not implement LaunchSearch`);

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Ripples */
const { St } = imports.gi;
const Tweener = imports.ui.tweener;

View File

@@ -1,4 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported RunDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
@@ -239,7 +240,7 @@ class RunDialog extends ModalDialog.ModalDialog {
this._errorMessage.set_text(message);
if (!this._errorBox.visible) {
let [errorBoxMinHeight, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
let [, errorBoxNaturalHeight] = this._errorBox.get_preferred_height(-1);
let parentActor = this._errorBox.get_parent();
Tweener.addTween(parentActor,

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