Compare commits

...

291 Commits

Author SHA1 Message Date
Matej Urbančič
f6ace7a325 Updated Slovenian translation 2020-06-01 22:09:11 +02:00
Florian Müllner
c38196dd85 Bump version to 3.34.5
Update NEWS.
2020-03-31 01:28:47 +02:00
Florian Müllner
059af4c4cd a11y: Change HC icon theme first
There are two ways for applications to provide a high contrast icon:

 1. install an icon into the HighContrast theme
 2. install a symbolic icon into the default hicolor theme

The latter is preferred nowadays, and implemented in the high-contrast
CSS variant by enforcing the symbolic icon style.

However together with the way we currently enable/disable high-contrast,
this can lead to the following race:
 1. the GTK theme is changed from HighContrast
 2. we reload the default stylesheet
 3. the icon style changes to "regular", so we request a
    new icon from the HighContrast icon theme
 4. the icon theme is changed from HighContrast
 5. we evict existing icons from the cache
 6. we reload icons for the new icon theme; however as we
    find a pending request (from 3), we re-use it
 7. the request from 3 finishes, and we end up with a
    wrong icon in the cache

The simplest fix is to change the icon theme before the GTK theme: Unlike the
theme name, the icon style is encoded in the cache key, so we won't re-use
an old (and incorrect) request in that case.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2414
2020-03-31 01:12:34 +02:00
Jwtiyar Nariman
aba60dcac8 Add Kurdish Sorani translation 2020-03-28 15:39:04 +00:00
Florian Müllner
3d7ee7856f keyboard: Fix fallback layout when using variants
Commit c1ec7b2ff meant to fall back to the base layout in case
a variant like `fr+oss` is set up, but as we are checking for
'+' on the array rather than the layout name, the fallback only
"works" for a layout that is literally called '+', whoops.

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


(cherry picked from commit d29e5765ba)
2020-03-23 15:28:03 +00:00
Florian Müllner
0a50b6ea01 networkAgent: Make searching VPN binaries asynchronous
Doing blocking IO in a graphical UI is bad, doing it in the compositor
is much much worse. So even if handling VPN requests is a relatively
rare event, doing it asynchronously is better.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:57 +01:00
Florian Müllner
c5dd9a9341 shell/network-agent: Wrap nm_plugin_info_new_search_file()
While we can use the libnm API directly from JS, the call will
synchronously load the VPN service descriptions from disk.
Previously we were lowering the impact by caching the result,
but as we stopped doing that, it becomes more important to address
the issue properly and move it off to a thread.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:57 +01:00
Florian Müllner
2756806f84 networkAgent: Drop VPN plugin cache
libnm doesn't only search for plugins in the regular VPN plugin directory,
but also in the legacy location and the directory pointed to by the
NM_VPN_PLUGIN_DIR environment variable (if set).

We don't monitor the additional directories, so it's possible for our cache
to become outdated.

Instead of trying to play catch-up with libnm's internals, do what nm-applet
does and use the appropriate API to look up the plugin on each request.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2386
2020-03-17 19:37:54 +01:00
Christian Hergert
bb9c286e3f shell: fix typo in comment
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050
2020-02-27 15:13:15 +01:00
Christian Hergert
cf2ab505a0 global: force fsync() to worker thread when saving state
The g_file_replace_contents_async() API can potentially call fsync() from
the thread calling into it upon completion. This can have disasterous
effects when run from the compositor main thread such as complete stalls.

This is a followup to 86a00b6872 which
assumed (like the rest of us) that the fsync() would be performed on the
thread that was doing the I/O operations.

You can verify this with an strace -e fsync and cause terminal to display
a command completed notification (eg: from a backdrop window).

This also fixes a lifecycle bug for the variant, as
g_file_replace_contents_async() does not copy the data during the operation
as that is the responsibility of the caller. Instead, we just use a GBytes
variant and reference the variant there.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1050
2020-02-27 15:13:15 +01:00
Jonas Dreßler
b7389b328c overview: Hide the overview on session mode hasOverview changes
If the sessionMode does not allow to show the overview, we should also
hide an already visible overview.

This fixes a bug where, if the lockscreen was shown while the overview
was visible, the Ctrl+Alt+Tab popup would allow navigating inside the
overview because the overview actor is still mapped.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1043
2020-02-25 20:14:15 +01:00
Jonas Ådahl
99d948559b closeDialog: Make dialog inactive while fading out
Otherwise the user might click Kill, which would crash if the fade-out
was triggered because a Wayland window was closed.

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


(cherry picked from commit 32fa060a62)
2020-02-21 08:19:35 +00:00
Florian Müllner
f21a0ff458 Bump version to 3.34.4
Update NEWS.
2020-02-16 15:51:30 +01:00
Dušan Kazik
ec852ab265 Update Slovak translation 2020-02-04 10:05:49 +00:00
Jor Teron
a8bb7c0a2a Update Karbi translation 2020-01-31 10:34:11 +00:00
Björn Daase
8a8c6e2f23 Revert "recorder: Switch to vp9"
This reverts commit d183f13456.
Switching to the vp9 encoder seemed like a good idea at the time but
unfortunately it also has the major drawback, that it leaks a serious
amount of memory every time it is used. See
https://gitlab.gnome.org/GNOME/gnome-shell/issues/256#note_692743
for more details.

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


(cherry picked from commit c61685e617)
2020-01-24 19:51:36 +00:00
Florian Müllner
f7fe7bc676 Bump verion to 3.34.3
Update NEWS.
2020-01-05 13:10:47 +01:00
Jonas Dreßler
a35f9a5226 polkitAgent: Only set key focus to password entry after opening dialog
Set the key focus to the password field only after we got a request
(and therefore know that a password is requested) instead of using
`setInitialKeyFocus()`. This way we don't try to focus the password
field by default if we aren't showing it (e.g. in case the user has no
password or is using fingerprint login).

Also we have to move the call to `grab_key_focus()` to happen after
`_ensureOpen()`, because otherwise the ModalDialog will set the focus to
one of the buttons while opening itself.

Cherry-picked from commit 70203b58ca.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2066
2019-12-25 12:56:46 +01:00
Florian Müllner
fb74394d58 keyboard: Stop accessing deprecated actor property
Commit 3d3dca4aa2 turned EmojiPager into a Clutter.Actor subclass,
but one place slipped through that still accesses it through .actor.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/2060
2019-12-20 14:37:31 +01:00
Florian Müllner
9f7b1bd677 Bump version to 3.34.2
Update NEWS.
2019-12-11 21:03:50 +01:00
Florian Müllner
afd2ce2353 popupMenu: Close when a system modal pops up
Just like switcher popups, popup menus don't play well together with
system modals, and generally have a lower priority. So just like
switcher popups, close popup menus when a system modal dialog pops
up.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1536
2019-12-11 20:35:13 +01:00
Florian Müllner
61fccf188a switcherPopup: Dismiss when a system modal dialog opens
As system modal dialogs may open without user interaction (for instance
polkit or network agent requests), it is possible for them to pop up
while the app/window switcher is up.

The current result of having both up simultaneously is clearly broken,
so we can either dismiss the popup or prevent the modal dialog from
opening. Assume that the dialog indicates a more important action and
should therefore take precedence, so go with the former.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1536
2019-12-11 20:35:13 +01:00
Florian Müllner
5043e6d6bd weather: Only require auto-location authorization if sandboxed
Since commit 87e60ed97843, geoclue no longer pretends that authorization
is useful for system-installed apps (as they can easily lie about their
ID). Unfortunately this broke our auto-location support in case Weather
is installed non-sandboxed, as we are waiting for an authorization that
will never happen.

Unbreak it by only requiring authorization when installed as Flatpak.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1823
2019-12-11 20:35:13 +01:00
Benjamin Berg
7be1729cde util: Place spawned processes into a systemd scope
This improves the separation from the shell for applications launched
with Alt+F2 and in a few other cases.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/863
(cherry picked from commit 4a6c2f1fe6)
2019-12-11 14:28:27 +01:00
Benjamin Berg
f92cb46b02 shell-global: Place launched applications into a systemd scope
This improves separation from the shells service scope for applications
launched using an XDG desktop file.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/863
(cherry picked from commit 086ba11621)
2019-12-11 14:28:27 +01:00
Umarzuki Bin Mochlis Moktar
56902542c7 Update Malay translation 2019-12-09 10:24:46 +00:00
Jonas Dreßler
523eea4527 closeDialog: Fix scale of dialog for x11 clients in Wayland sessions
We missed this case in b6e57a5ae8,
XWayland clients obviously don't use MetaWindowWayland and thus they
don't apply the double scaling that commit was meant to fix.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/884
2019-12-04 23:41:02 +01:00
Florian Müllner
a7b0e96304 switcherPopup: Fix scrollable check
When commit c6cea277e replaced Shell.GenericContainer, the check
whether the required width exceeds the avilable width was changed
from using the minimum widths of items to the natural width of the
scroll view.

That doesn't work correctly, as the *natural* width may well exceed
the actually used width: SwitcherList bases its width request on
children's minimum sizes to force labels to ellipsize.

Fix this by using the minimum width of the scroll view's child instead.

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


(cherry picked from commit 867cffaf20)
2019-11-29 17:53:58 +00:00
Florian Müllner
bb24df2f9d calendar-server: Use correct timezone for all-day events
Since commit 28c535e34, we use the timezone associated with the ICalTime
instead of the default timezone when converting to time_t. However while
that is correct for most events, for ICalTimes that don't have a timezone
associated we still want to fall back to the default timezone instead of
UTC.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1895
2019-11-28 14:19:19 +01:00
Joonas Henriksson
9150cbca3e theme: Add light styling to message buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/865
2019-11-27 20:17:57 +01:00
Yi-Jyun Pan
35bb67bb2f Update Chinese (Taiwan) translation 2019-11-27 16:07:32 +00:00
Joonas Henriksson
d4c2f9d0ef appIcon: Draw running dot above the overview icon
Prevent the app-well-app-running dot from getting unintentionally
hidden behind the overview-icon background by initializing the
running-dot after its sibling overview-icon.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/866
2019-11-27 03:20:05 +01:00
Daniel García Moreno
e211c68a5c texture-cache: Remove also scaled keys from the cache
We're storing in the texture cache images and scaled images appending
the scaling factor to the key. When a file changes the cache key
corresponding to that file is removed, but not the keys for the scaled
ones so that images in the cache are never reloaded.

This patch removes all keys from the cache related to the file that
changes, including those with the scaling factor.

A new set (hash table) was added to keep track of scale used to be able
to remove all possible images in the cache.

When the KEY is removed from the cache, we can look now in the scale set
for and each scale we also remove the key "KEY1.000000", "KEY2.000000",
etc.

Assuming that the number of used scales is small (I would typically
expect one or two), the overhead should be negligible.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/567
2019-11-26 14:21:46 +01:00
Benjamin Berg
af95883807 data: Enable clean session shutdown after gnome-shell failure
If the GNOME shell crashes, we run a service that may disable
extensions. This is important so that users will not be locked out of
their own session in case an extension is causing crashes.

As this is a very agressive action, we tried to only do this in the
first two minutes of the session. Unfortunately, the logic was broken
and would result in an unclean session shutdown.

Fix this by using the newly introduced gnome-shell-disable-extensions
file. This is created by the extension subsystem for a period of time to
indicate the extensions may be the cause of a gnome-shell failure.

See
  https://gitlab.gnome.org/GNOME/gnome-session/issues/43
for a log of the bug happening and the gnome-session part to fix this.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/858
2019-11-25 23:38:32 +01:00
Benjamin Berg
91f41105d5 extensionSystem: Create a file to flag that extensions are being loaded
When the extension system is loaded, create the
gnome-shell-disable-extensions file in the users runtime directory. This
file is automatically removed 60s later. The sole purpose of this file
is to be consumed by the systemd units. If the file exists, the systemd
units will disable extensions when the gnome-shell fails.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/858
2019-11-25 23:38:32 +01:00
Florian Müllner
45fa520cca extensions-tool: Fix removing from settings list
When removing a string from a settings list, we iterate over all
existing entries and copy all strings except the one that's being
removed to a new list, which is then written to GSettings.

However we currently always increment the index, so we end up with
a NULL entry in place of the removed entry, which is then interpreted
as the end of the list. In other words, we also remove all entries
that follow the removed string.

Fix this by looping over the list entries instead of the index, and
only increment the index for entries we copy.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1946
2019-11-25 21:05:32 +01:00
Florian Müllner
334762ee9e introspect: Fix whitelist check
The whitelist is a list of well-known D-Bus names, which we then search
for the unique name we get from the method invocation - unsuccesfully.

Fix this by watching the bus for any name in the whitelist in order
to maintain a map from wel-known to unique name that we can use for
matching.

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


(cherry picked from commit eee1ab4890)
2019-11-25 19:20:01 +00:00
Joonas Henriksson
88e3dfa104 theme: Add :active styling to message-close and media control buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Joonas Henriksson
4b89314813 theme: Add message close button styling
Since the notification message close button had no border, or mouse
over effect, there was no way to determine whether the mouse cursor
were over the button.

Improve this by adding a message-close-button class for the close
button, and a styling for its hovered state, based on media control
button styling.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Joonas Henriksson
a9fa4cc49e theme: Darken hovered message-media-control button
Increases contrast between normal and hovered states in
message-media-control buttons. Previously there was very little
difference between the two states, making it hard to distinguish
whether the mouse cursor was over the button.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/855
2019-11-25 17:12:23 +01:00
Jonas Dreßler
9476c9c4ca magnifier: Use new cursor tracker API to keep wayland focus while hidden
Since commit mutter/a2a8f0cda we force the focus surface of the
meta-wayland-pointer to NULL while the pointer is hidden. This
introduced an issue with the magnifier, where we use
`set_pointer_visible` to hide the real cursor and show our own cursor at
the correct position: Because the meta-wayland-pointer is still used to
communicate with Wayland clients, the UI of the windows will not respond
to mouse movement anymore as soon as the real cursor is hidden.

To fix this, use the newly added API of MetaCursorTracker to switch back
to the old behavior while the magnifier is hiding the system cursor.

In the future and as a more correct fix, we might want to rewrite the
magnifier so it doesn't have to hide the cursor and can simply show the
default one (eg. by scaling the actual view instead of a clone of the
view).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/754
2019-11-25 15:21:29 +00:00
Jonas Dreßler
24df43d579 magnifier: Use own showSystemCursor() instead of set_pointer_visible()
We already have our own function to show the system cursor, use it!

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/754
2019-11-25 15:21:29 +00:00
Ricardo Silva Veloso
363336e4a1 Update Brazilian Portuguese translation 2019-11-25 14:12:45 +00:00
Joaquim Rocha
070c784412 polkitAgent: Use dialog as confirmation when the user has no password
When a user has no password and a polkit authentication is started,
instead of blindly initiating the admin session, show the regular
"Authentication Requested" dialog (but without the password entry). This
makes sure that the user's admin session is only effectively started
after the user chooses to proceed with the authentication, which
provides an extra confirmation step that can be vital for critical
tasks.

To do this, we show the dialog inside `_onUserChanged()` right after the
dialog was created instead of calling `performAuthentication()` from
`_onInitiate()`. The bug mentioned in `_onInitiate()` is no longer an
issue since we show the dialog in all cases now anyway.

Ideally we should use a different wording than "authentication" when the
user has no password set, and use "confirmation" instead. However polkit
already sends the requests with such messages (e.g. "Authentication is
required to configure software repositories"), and it's important to
show those to the user, so this patch keeps the regular wording.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/829
2019-11-24 20:23:42 +01:00
Jonas Dreßler
455eb67a49 polkitAgent: Update user name on user changes
Right now we only update the user avatar on the user-changed signal, but
since we also display the users real name we should also update that if
the user changes.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/788
2019-11-24 20:23:42 +01:00
Jonas Dreßler
23cc59f52a polkitAgent: Fix a typo of a signal name
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/788
2019-11-24 20:23:42 +01:00
Jonas Dreßler
19bb459a57 appDisplay: Add a timeout when switching pages during DnD
Currently when dragging an icon to the space above or below the appGrid
to switch pages, we do so very quickly without checking when the last
page-switch happened. This makes it hard to move icons to pages which
are not the first or the last one, since the other pages are skipped
very quickly.

To fix this, add a timeout of 1 second that blocks switching pages after
a page-switch using drag overshoot occured.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1693
2019-11-24 20:18:42 +01:00
Florian Müllner
48477443fa appDisplay: Add threshold after overshoot page switches
We currently always switch app pages when a dragged app icon
moves outside the grid boundaries, regardless of any previous
page switches. This makes it too easy to switch multiple pages
accidentally, so add a small threshold that the icon has to
move back towards the grid before allowing another page switch.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1693
2019-11-24 20:17:47 +01:00
Jonas Dreßler
40b2fbf465 appDisplay: Simplify event blocking while folder is opened
There's no need for a `inhibitEventBlocker` interface. Since we connect
to "open-state-changed" of our folders in the AllView anyway, we can
just make the event blocker visible while a folder is opened, and hide
the event blocker during DnD.

This allows keeping the eventBlocker reactive at all times and fixes an
issue where DnD to create a new folder is impossible if no folders are
present because the eventBlocker would not get inhibited.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1652
2019-11-23 18:51:44 +01:00
Jonas Dreßler
7800bd2158 appDisplay: Ensure we don't recreate existing AppIcons for folders
This was missed in 910037f014, make sure
we do the same thing for AppIcons that are created when reloading
folders.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/851
2019-11-23 15:30:03 +01:00
Jonas Dreßler
d4f07410a1 appDisplay: Add missing .actor
This was missed while cherry picking
b88f7d0655 to 3.34.

Thanks to Térence Clastres for finding the issue and testing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/852
2019-11-23 22:00:37 +01:00
Florian Müllner
64b62de5df keyboard: Try harder to find a matching layout
While we support a reasonable list of layouts nowadays, we don't
include many variants like `fr+oss`. Instead of directly falling
back to the `us` layout, try stripping the variant first, as the
base layout is likely closer to the expectation than `us`.

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


(cherry picked from commit c1ec7b2ffa)
2019-11-23 00:38:53 +00:00
Florian Müllner
9b0d42309b screenShield: Replace child properties
It turns out https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/780
helped with some redrawing issues on the screen shield, so cherry-pick the
relevant bits to the stable branch.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1836
2019-11-23 00:19:26 +00:00
Florian Müllner
cf249ab870 switcherPopup: Fix last commit
The surrounding code has diverged on master, so the cherry-picked
commit doesn't work without adjustments, whoops.
2019-11-23 01:05:31 +01:00
Florian Müllner
c752682ab9 switcherPopup: Improve modifier-less keybinding navigation
Commit c899453800 lifted the requirement of switcher keybindings
to contain a modifier, however it is currently only possible to
finish it by letting it time out.

Improve that by also accepting space/enter key presses to confirm the
selection immediately.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1883
2019-11-23 01:00:21 +01:00
Jonas Dreßler
a6e4ef862c switcherPopup: Use roundtrip time when the popup is modifier-less
The noModsTimeout obviously finishes inside a timeout callback, which
means `global.get_current_time()` might return Clutter.CURRENT_TIME (ie.
0) when called inside it, because it's not called while handling an
event. This means when switching apps or activating a window, the
timestamp passed to `activate_window` may be 0, which is the reason why
the altTab switcher is currently broken when using modifier-less
keybindings.

Fix that by using `meta_display_get_current_time_roundtrip`, which
always return a valid timestamp, instead of
`shell_global_get_current_time`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/847
2019-11-23 00:59:57 +01:00
Philip Chimento
8d2365b7b9 appDisplay: Don't crash if app is missing categories
g_desktop_app_info_get_categories() may return null. In that case, the
previous code would fail to create a folder when dragging an app with
no categories onto another app. Instead, simply continue with the next
app info.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/782
2019-11-23 00:57:59 +01:00
Florian Müllner
03219f745d panel: Update window section items on title changes
We currently only update the windows section when either the focus
app changes, or when the app's windows change (that is, a window is
opened or closed). This allows the menu item labels to become stale
if the window title changes after one of those events (for example
when switching tabs).

Fix this by updating menu items when the corresponding window
title changes.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1830
2019-11-22 01:33:45 +01:00
Philip Chimento
7d34dee77f power: Handle "100% but charging" case
I've observed that UPower can occasionally report a charge level of 100%
while the state is still "charging". This usually doesn't last very long
but it is noticeable because the power icon changes to a "missing icon"
icon. This will handle that rare case correctly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/814
2019-11-22 00:33:23 +01:00
Jonas Dreßler
f0e59ea088 closeDialog: Fix dialog size when using geometry scaling
The close dialog is added as a child to MetaWindowActor, and, in Wayland
sessions, since commit [1] MetaWindowActor applies a transformation
matrix which scales all it's children using the geometry scale factor.
Now because the dialog actor is not a window (i.e. a MetaSurfaceActor),
but a subclass of StWidget, the scale factor is also applied to the
properties of the dialog by StThemeNode, so we end up applying the
geometry scale twice to the close dialog.

Fix this by applying the inverted scale to the dialog, which leaves the
scaling only to MetaWindowActor. This means we also can't apply a pivot
point other than 0 to the dialog actor, so apply the 0.5-pivot point to
the `_dialog` child of the Dialog class (the actual visible dialog box)
and also perform scaling animations on this child.

[1] https://gitlab.gnome.org/GNOME/mutter/commit/fb9e8768

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/783
2019-11-22 00:30:23 +01:00
Georges Basile Stavracas Neto
f8a90f6583 appIcon: Remove drag monitor on destroy
It may happen that the app icon is destroyed with a drag
monitor still around, in which case, a load of warnings
will be shown.

Make sure to remove any pending drag monitor on destroy.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:12 -03:00
Georges Basile Stavracas Neto
aa1d297bdf folderView: Reset schemas before removing the folder
When removing the last icon of a folder, FolderView first removes
the folder from org.gnome.desktop.app-folders.folder-children, then
proceeds to reset all its keys, which removes the relocatable schema.

That order of operations turns out to be problematic. Removing the
folder from 'folder-children' destroys the folder icon, which in turn
destroys the folder view, which throws a load of warnings in the
journal.

Fix that by removing the folder after resetting the schema keys. In
fact, what we're doing here is not using 'this' anymore.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:11 -03:00
Georges Basile Stavracas Neto
b88f7d0655 baseAppView: Destroy icon when removing
We cannot rely on the garbage collector to do that in a timely
manner, so destroy it explicitly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:08 -03:00
Georges Basile Stavracas Neto
59daa4192c allView: Rename variable
The variable that holds the list of application icons is
called 'newApps', but that technically was never true,
since we only create new app icons when necessary.

Rename it to 'appIcons'.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/841
2019-11-21 20:13:06 -03:00
Georges Basile Stavracas Neto
d08cd1f523 allView, frequentView: Only create icons when necessary
The views (AllView and FrequentView) build a list of all applications
they contain. BaseView then diffs between what's currently added, and
what needs to be added, and removed.

This approach has a problem though: creating an AppIcon or a FolderIcon
connects to various signals, and we confuse the garbage collector.

When building the list of applications, instead of always creating new
icons, try to use already existing icons first.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1610
Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1694
2019-11-21 20:13:04 -03:00
Florian Müllner
a85cddada0 polkitAgent: Fix spinner
Commit 6af25b282c accidentally changed the case of the property.

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


(cherry picked from commit acaa9f7f77)
2019-11-21 21:57:55 +00:00
cunidev
ae8568a2e0 Increase .calendar-today visibility
Adds some needed contrast to the calendar widget current day, solving #1873.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/823
2019-11-20 13:45:58 +01:00
Joonas Henriksson
4a3ca40c48 appMenu: Hide stopped spinner actor
Get rid of leftover empty space from the application menu panel
button, that was used by the spinner actor, which remained visible
even after the spinner had stopped.

Fixes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1679
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:34 +02:00
Joonas Henriksson
e257be64d0 animation: Add parameter for hiding stopped Spinner actor
Not hiding leaves the empty actor space visible, which may have an
undesirable effect on the parent element's size or spacing/padding.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:34 +02:00
Joonas Henriksson
96ac00b53c animation: Turn Spinner animate parameter into Params option
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/834
2019-11-19 23:25:29 +02:00
Florian Müllner
7e8884a601 windowManager: Replace left-over calls to _removeEffect()
Those calls no longer exist on master, so the cherry-pick commit in
22b6a09cd7 missed them.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1884
2019-11-11 22:39:58 +01:00
Stas Solovey
ef726bf313 Update Russian translation 2019-11-11 19:27:16 +00:00
Florian Müllner
a43c22e3af windowManager: Complete interrupted size change effects
Resizing effects are more finicky as other effects, as the actual
animation is delayed until we receive the ::size-changed signal.

However that signal may never be emitted if the window is destroyed
just after starting the size-change effect, in which case the effect
is never completed, blocking mutter from destroying the corresponding
window actor.

Address this by tracking when a resize effect is pending, and complete
the effect when appropriate.

https://gitlab.gnome.org/GNOME/mutter/issues/655
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/815
2019-11-08 23:20:17 +01:00
Florian Müllner
22b6a09cd7 windowManager: Use Sets to track ongoing effects
We only care whether an effect is ongoing for an actor, not about
any particular order. Sets are more convenient than arrays in that
case, so use them instead.

https://gitlab.gnome.org/GNOME/mutter/issues/655
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/815
2019-11-08 23:20:17 +01:00
Florian Müllner
65110968c5 ci: Fix checking out mutter on stable branches
For stable branches, we currently only check out the correct mutter
branch for merge requests. For the regular pipeline, our code to
determine the current shell branch fails because CI runs on a
temporary "pipeline/12345" branch that doesn't exist for mutter.

Switching to the correct gitlab environment variable fixes that.

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


(cherry picked from commit fd5989e99a)
2019-11-06 22:59:50 +00:00
monday
d142f59478 theme: Adjust system-menu-action buttons
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/802
2019-11-05 14:16:09 +01:00
Milan Crha
c1ecd304e7 calendar-server: Uses wrong timezone for event times
The conversion to UTC/time_t time was not using correct timezone.

Closes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1714
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/806


(cherry picked from commit 28c535e341)
2019-11-05 11:58:17 +00:00
Philip Chimento
750c5acd30 dnd: Skip drag target when its acceptDrop() throws an exception
In the case of bugs in a drag target's acceptDrop() function, it may
throw an exception. In the previous code, this would break out of the
loop entirely and never cancel the drag, so the mouse button release
event would be ignored and you would have to press Esc to get out of the
drag.

In this change, if acceptDrop() throws an exception, we log it and move
on to the next parent target instead.

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


(cherry picked from commit 055c007ac2)
2019-10-24 23:08:08 +00:00
Robert Mader
246150d8b6 shell-screenshots: Do not pass a clip for window screenshots
Design team wants us not to clip away the shadows, lets do that.

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


(cherry picked from commit 20f4fc7c87)
2019-10-21 09:46:37 +00:00
Andrew Watson
072a9a4842 workspace: Sort windows in overview grid using cached center
When accessing properties on ClutterActor for size and position there is
a notable access time overhead. This overhead adds considerable user lag
when opening the overview if many windows are open.

This is primarily due to these properties being accessed while sorting
WindowClone instances by their window's center for placement in the
overview. By pre-computing this center value only once when
initializing WindowClone, the induced lag can be significantly reduced.

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


(cherry picked from commit d91927674d)
2019-10-17 08:07:22 +00:00
Marco Trevisan (Treviño)
7149da3f4f screenShield: Compute lock timeout fade duration using animation settings
When the screen is marked as idle, we normally start a fading animation and
a timeout to finally lock the screen. This timeout is configured using the
fade time if no longer delay is set in settings.

However if animations are disabled or slowed-down/up, the fade time is
different from the STANDARD_FADE_TIME and so we might end up showing the
lock shield without actually locking for STANDARD_FADE_TIME in the disabled
or slowed-up animations case, or locking too early in case of slowed-down
animations.

So, just adjust the timeout time using the same logic of animations so that
this value is matching all the times.

Related to https://gitlab.gnome.org/GNOME/gnome-shell/issues/1744

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


(cherry picked from commit ab6a629955)
2019-10-16 23:57:24 +00:00
Florian Müllner
6c2a82258e environment: Only disable unredirection of ongoing transitions
When a transition is set up with a delay, it may be removed before it
actually started. We won't get a ::stopped signal in that case, with
the result that we currently end up with a mismatched unredirection
disabling.

Address this by only disable unredirection once the transition has
actually started.

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


(cherry picked from commit 38ad1d7c13)
2019-10-14 08:54:20 +00:00
Marco Trevisan (Treviño)
279024afc2 js: Replace Tweener time leftovers with ease duration
In some places we were not properly animating the actors as still using the
non-existent 'time' property instead of 'duration'

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/758
2019-10-10 02:14:28 +02:00
Marco Trevisan (Treviño)
ef8000d2e6 animation: Finish porting to clutter transitions
Animation when stopping the spinner was still using the old
parameters that not working, although if silently failing.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/758
2019-10-10 02:08:59 +02:00
Florian Müllner
986600ab31 Bump version to 3.34.1
Update NEWS.
2019-10-09 02:50:29 +02:00
Florian Müllner
3d39b32a0b Revert "windowManager: Use new reorder_workspace() API"
It's too easy to break, so revert to the old code until we
figure out a fix.

This reverts commit ff9bb5399b.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1497
2019-10-08 21:11:19 +02:00
Florian Müllner
6205d5eb27 windowManager: 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/issues/1497
2019-10-08 21:11:19 +02:00
Carlos Garnacho
a722b4c51d ibusCandidatePopup: Use an internal actor to track IM focus position
We share this actor with other shell menus, which arguably track a different
"cursor" as we care of the caret/anchor text positions, and menus care about
pointer click coordinates.

Use a standalone actor for this, so popups/IM are entirely decoupled.

Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1571
2019-10-08 17:12:43 +00:00
Marco Trevisan (Treviño)
31fe517007 shell-global: Ignore modal operations if we have no compositor
Modal dialog actions might be triggered during display closing, and in such
cases we should just ignore the requests.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/746
2019-10-08 17:51:52 +02:00
Marco Trevisan (Treviño)
31d915a38a shell-global: Disconnect from stage events on X11 display close
As per GNOME/mutter!385 [1], the compositor is finalized an its pointer
cleared on display close.

However, since the shell reacts to such events instead of controlling them,
when the shell is stopping or restarting and its display closing, the shell
stage destroys its children after the display closing is finished and during
this process the focus is unset, causing focus_actor_changed() to be called
and thus calls to meta_stage_is_focused() which deferences the now NULL
compositor, leading to a crash on shutdown.

Since after this point we should just ignore any stage event, disconnect
from them all.

[1] https://gitlab.gnome.org/GNOME/mutter/merge_requests/385

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/746
2019-10-08 17:49:30 +02:00
Florian Müllner
e00878ab75 shellDBus: Don't assume devices have a node
Clutter.InputDevice.get_device_node() may return null. Handle that
case when building the 'AcceleratorActivated' vardict parameter.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1641
2019-10-07 21:24:13 +00:00
Lubomir Rintel
3b5675b79a networkAgent: add support for SAE secrets
NetworkManager supports "WPA3 Personal" networks for some time now, they
use the SAE authentication. Add support for it alongside other
password-based mechanisms.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/751
2019-10-07 22:44:39 +02:00
Alan Mortensen
ee97512bcc Updated Danish translation 2019-10-06 18:16:32 +02:00
Iain Lane
085531b43d main, util: Notify systemd once we are fully initialised
If graphical applications want to start from systemd units, they need to
start after we're properly ready to display them. This is particularly
important under X where `_GTK_FRAME_EXTENTS` and other xprops are needed
to have the right theming.

We're doing this in an idle callback so that the dynamic starting of
`gnome-session-x11-service.target` (which launches `gsd-xsettings`) as
the result of a signal emission happens before us signalling we're ready
for later things to start.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/750
2019-10-04 15:40:05 +00:00
Ryuta Fujii
9e8b97d474 Update Japanese translation 2019-10-04 14:54:06 +00:00
Ryuta Fujii
a3a7953704 Update Japanese translation 2019-10-04 14:52:49 +00:00
Marco Trevisan (Treviño)
92c0171aeb lightbox: Show the actor before easing it
As per clutter optimizations in should_skip_implicit_transition() any
transition will be ignored if applied to an actor with unmapped clones.

Since we initialize the lightbox as hidden, when we use it standalone (as it
happens for the long fade in screenShield) the transition will be ignored.
This causes the lockscreen fade-out after the idle delay not to work, but
instead to have an apparently locked system that is instead not locked at
all.

So, just ensure that the lightbox actor is visible before applying to it any
transition.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1683
2019-10-03 15:26:13 +02:00
Marco Trevisan (Treviño)
6a6d66486d ibusManager: Cancel the preload engines timeout on clear
This is created when preloading but never cancelled if ibus disappears

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/743
2019-10-02 18:19:53 +02:00
Marco Trevisan (Treviño)
1cc766d636 ibusManager, inputMethod: Cancel async ibus calls chain on disconnect
The shell tries to spawn the ibus daemon on startup if unavailable, however
as per commit 8adfc5b1 we also force restarting it once the X11 server is
available.
Unfortunately this could cause a race if we disconnect while we were already
connected to an ibus daemon, but still in the process of going through the
various nested calls.
In fact the ::disconnect callback didn't stop any further async ibus call
that, even if failing, would have eventually triggered the emission of a
'ready' signal and to the Keyboard's callback, leading under X11 to a full
grab owned by ibus daemon.

In order to avoid this and keep control of the calls order, use in both
IbusManager and InputMethod a cancellable that is setup before connecting to
the bus, and that is cancelled on disconnection.
Then handle the finish() calls properly, using try/catch to validate the
returned value, taking in account the potential error and just not
proceeding in case of cancellation.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1712
2019-10-02 18:19:53 +02:00
Takao Fujiwara
60cad01880 inputMethod: Do not change IBus.Capabilite by focus events
gnome-shell calls ibus_input_context_focus_in() in InputMethod.focus_in()
but the event is not actually forwarded to panels and engines in GNOME
Wayland because gnome-shell changes IBus.Capabilite by focus events and
disables IBus.Capabilite.FOCUS when ibus_input_context_focus_in() is called.

IBus.Capabilite is assumed a fixed value per input context in the
first place and it should not be changed by focus events.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/573
2019-10-02 08:40:27 +00:00
Ask Hjorth Larsen
63c9a6efd0 Updated Danish translation 2019-10-02 05:35:36 +02:00
Marek Černocký
1d1b42756f Updated Czech translation 2019-10-02 03:57:00 +02:00
Matej Urbančič
a95601afdb Updated Slovenian translation 2019-09-28 21:13:30 +02:00
Matej Urbančič
2dbdf792db Updated Slovenian translation 2019-09-26 22:02:27 +02:00
Fabio Tomat
e23ce37e62 Update Friulian translation 2019-09-26 14:20:38 +00:00
Dušan Kazik
a05cb76e0d Update Slovak translation 2019-09-26 06:43:01 +00:00
Florian Müllner
60cab56f86 shell-util: Handle NULL from meta_window_get_image()
Until commit 506b75fc7f we got away with not handling a NULL return
value, as cairo_surface_destroy() deals with a NULL surface; the same
isn't true for get_width/get_height, so guard to code in question to
prevent a crash.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1678
2019-09-25 14:34:27 +00:00
Nathan Follens
70a5c3875c Update Dutch translation 2019-09-25 11:11:56 +00:00
Benjamin Berg
0fdbde9101 main: Remove NOTIFY_SOCKET from environment
It is only used exactly once to notify systemd about the service
startup. So unset it as soon as possible as it can leak into
subprocesses we spawn otherwise.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/741
2019-09-23 11:09:39 +02:00
Jonas Dreßler
2156577333 slider: Unset signal IDs when ending the slider drag
Unset the signal IDs we connected to when starting the drag. Otherwise
we get error messages if a touch drag is ended after a mouse drag
happened because the signal IDs are still set but no signals are
connected.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/740
2019-09-22 22:20:41 +00:00
Ryuta Fujii
f3e09b2b2f Update Japanese translation 2019-09-22 11:29:14 +00:00
Ryuta Fujii
6180f59c13 Update Japanese translation 2019-09-22 11:27:23 +00:00
Robert Mader
506b75fc7f shell-util: Do not scale the clip in get_content_for_window_actor()
This is now handled in Mutter. Also, respect the result size instead
of assuming it to be equal to the clip size, as the clip takes actor
coordinates while the result takes buffer coordinates.

This can be fixed in a future API iteration.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/728
2019-09-20 17:27:34 +00:00
Fran Dieguez
a0d0a17d68 Update Galician translation 2019-09-20 17:19:17 +00:00
Florian Müllner
92e5713e29 screenShield: Stop using deprecated actor property
Both LoginDialog and UnlockDialog are now actor subclasses, so stop
using the deprecated actor delegate that will trigger a warning.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
856c32db91 unlockDialog: Use inheritance instead of composition
The screen shield creates the unlock dialog based on the session mode.

However since commit 0c0d76f7d6 turned LoginDialog into an actor
subclass (while UnlockDialog kept using the delegate pattern), it is
no longer possible to handle both objects the same way without warnings.

Allow this again by turning UnlockDialog into an actor subclass as well.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
7b45ffa511 loginDialog: Stop using deprecated actor property
Commit 0c0d76f7d6 made the class an actor subclass, so the actor
property is just a deprecated synonym of the object itself.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
2019-09-20 16:58:00 +00:00
Florian Müllner
b6754d7db7 environment: Try harder to find a transition
When easing, we need the transition of one of the involved properties
to connect our callbacks. Currently we simply get the transition for
the first property, however as Clutter optimizes the case where a
property doesn't actually change, that transition may be NULL even
though we still animate other properties.

So instead of only looking at the transition of the first property,
try to find a transition for any of the involved properties.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1572
2019-09-20 16:40:46 +00:00
Marco Trevisan (Treviño)
2a9977a5b3 layout: Don't use the actors pick workaround on update regions
As per introduction of geometric picking in mutter [1], the workaround we
had consisting in picking all the actors to ensure that all the stage
projections were computed to get valid actors stage-transformed coordinates
and sizes is not working anymore as there is more caching involved.

However since this can be now handled properly in mutter [2], initializing a
valid projection matrix since the beginning, we can get rid of the
workaround.

[1] https://gitlab.gnome.org/GNOME/mutter/commit/14c706e51
[2] https://gitlab.gnome.org/GNOME/mutter/merge_requests/803

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/734
2019-09-20 16:05:32 +00:00
Marco Trevisan (Treviño)
dab60d5580 renameFolderMenu: Use a custom menu item inheriting from PopupBaseMenuItem
The RenameFolderMenu uses the internal box as a menu item, while PopupMenu
expects to have PopupBaseMenuItem based children with a delegate set.

Instead of using a custom menu with a customized box acting as menu
item,just add a RenameFolderMenuItem that inherits from the parent,
adjusting the features as we need them. In fact, the rename folder menu item
doesn't need any label, padding or default styling so we can reuse
PopupMenuBaseItem after we use our styling properties and we set the
Ornament to HIDDEN.

To get the proper style in place, define rename-folder-popup and
rename-folder-popup-item to override the default popup-menu-item rule
padding instead of using margins.

Pass the menu item as menu's focusActor as this will key-focus it on pop-up,
by overriding the key_focus_in() vfunc we can then delegate the focus
handling to the entry's clutter-text.

Also override the map() vfunc in order to update the entry's content before
mapping the entry.

Finally, use the item's activate method in order to tell the parent menu
we're done with it and that the menu can be closed.

As consequence we can also remove the menu's popup() method, and just use
the default open().

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
8e3aac8ed7 renameFolderMenu: Move to non-legacy coding style
Use proper indentation on multi-line methods calls and use single quotes on
button label.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
147cb53140 renameFolderMenu: Set the entry as menu focus actor
When the rename folder menu is opened the text entry is expected to be
focused and selected for a quick editing.
While this is required it doesn't actually happens since PopupMenu by
default gives the key focus to the source actor, that is then free to pass
the key focus to the menu if there's an user interaction.

In this case however, we want the text entry to be focused once we prompt
the menu, so just use the PopupMenu's focusActor property to ensure it will
handle it for us.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1604
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
54f369404a popupMenu: Add focusActor property to define the default focus actor
The PopupMenuManager is supposed to grab and focus the menu actors, with
normal menus we always need to grab the actual menu but set the key focus to
the source actor so that it will be able to move the focus to the menu
child, if requested.

However there are menus such as the RenameFolderMenu that requires the
key-focus once prompted, so provide a focusActor property (defaulting to the
sourceActor) that can be set in order to define the actor to give the
keyboard focus to, when the menu is popped-up.

Fixes https://gitlab.gnome.org/GNOME/gnome-shell/issues/1604
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
af1aabff75 popupBaseMenuItem: Add support for Hidden Ornament
The menu item ornament is used to put dots or checks in menus or otherwise
to define a padding for a label.
However in some cases we want to create a menu item with no left (in ltr)
padding.

In order to do that, define a HIDDEN Ornament mode that completely hides the
ornament actor.

The naming here might be confusing as this should probably be called NONE,
while the default mode is the invisible one, but it's too late to change it
now.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
d6ba6dc554 renameFolderMenu: Don't save the source
The source actor is already tracked by the PopupMenu internally as
sourceActor, while nothing in RenameFolderMenu uses the source, so we can
drop this.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Marco Trevisan (Treviño)
42188b7698 folderIcon: Remove duplicated addMenu call
The RenameFolderMenu is added already to its menu manager, so no need to
repeat the operation.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/720
2019-09-20 15:53:42 +00:00
Jonas Dreßler
48adb2ef4b workspace: Fix an incorrect signal check
While commit 3094f863 was intended to cancel the ongoing idle hide
timeout before we start a new one, a mistake slipped in there while
rebasing: Obviously we should check if the signal id is NOT 0 here.

This didn't prevent timeouts being started while old ones are still
running and did override `this._idleHideOverlayId`, which caused the old
timeouts to run indefinitely after an overlay actor was destroyed
because we fail early (and don't return TRUE) in `_idleHideOverlay()`.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/735
2019-09-20 11:50:24 +02:00
Jonas Dreßler
f8e648b7e3 appDisplay: Animate DnD app icons at the position they were dropped
Indicate whether dropping an app icon was successful or not by using the
newly added `animateLaunchAtPos()` API of AppIcon which starts a zoom
out animation of the icon at the position the drop happened.

To get the position of the drag actor, we have to forward the arguments
passed to `acceptDrop()` and `handleDragOver()` to the internal drag
handlers of the WorkspaceThumbnails. We can use this position directly
without transforming it to stage coordinates because the actor is a
child of `Main.uiGroup` and the animation actor will also be a child of
this container.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
daa5452af2 appDisplay: Add API to animate launch at given position
Add a `animateLaunchAtPos()` method to the AppIcon class to animate the
launch of an app at a given position. This allows for a visual
indication of whether dropping an app icon using DnD was successful at
the position the drop happened in a later commit.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
259874d731 workspace: Return results of forwarded acceptDrop
Return the results of calls to acceptDrop that we forwarded to the
Workspace object.

This fixes a bug where app icons that were dragged and released above a
window clone would get animated back to their original position
(indicating that nothing happened) even though they opened correctly.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
23344701de overview: Only accept AppIcon drops if the app can open a new window
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
00e95de114 shell-app: Never allow opening new windows while an app is starting
We allow opening new windows as a fallback in case the app doesn't give
us explicit information about it, but we don't want to allow opening new
windows if we're unable to ask for this information (we can only use the
APIs to get this information while the app is RUNNING).

So always return FALSE in case the app is STARTING, always return TRUE
in case the app is STOPPED (starting an app always opens a new window)
and go through the usual checks in case the app is RUNNING (and
eventually fall back to FALSE).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Dreßler
942758bb30 workspace: Use AppIcon.app to check action-support by the drag source
`AppIcon.shellWorkspaceLaunch()` can easily be replaced by checking for
`AppIcon.app` and calling `AppIcon.app.open_new_window()` directly.

For compatibility and to prevent breaking extensions implementing the
function, keep supporting the `shellWorkspaceLaunch` API in AppIcon
while logging a deprecation warning. Also keep supporting the API on
drag sources (without deprecating it) to allow extensions to define
custom actions on their drag sources.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/121
2019-09-18 17:14:16 +00:00
Jonas Ådahl
e0947b01bd introspect: Check whitelist also for GetRunningWindows()
Otherwise the xdg-desktop-portal-gtk screen cast widget won't work.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/732
2019-09-18 16:17:25 +00:00
Daniel García Moreno
cf00231aa8 st: Fix box-shadow drawing with prerendered_texture
The use of box-shadow on a StWidget that has a background-gradient was
not been rendered correctly, the shadow borders was calculated inside
the st_theme_node_prerender_shadow function and in the case that we've a
prerendered_texture the max_borders was not calculated and are 0.

This patch creates a new static function to compute shadow maximum
borders copying the code from st_theme_node_prerender_shadow, and call
this new method in the case that we've a prerendered_texture.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1186
2019-09-18 16:09:36 +00:00
Jonas Dreßler
5c3f4f5f8b workspace: Remove unused properties of WindowClone
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
5f10047b58 viewSelector: Only reset search entry if it has key focus
If the search entry does not have any text typed in and a button press
happens outside of the search entry, we set key focus to NULL to make
the search entry appear unfocused.

This is quite intrusive and can easily cause unwanted focus changes, so
change the captured-event handler to only call `reset()` if the search
entry actually is focused.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
3094f86334 workspace: Reset idle hide timeout for overlays on reentry
Instead of returning and waiting until the old timeout is finished,
start a new idle hide timeout for the overlay when the pointer enters a
window clone. This makes sure the timeout for hiding the overlay after
the pointer left the clone mostly stays the same (except when leaving
the clone via the title or the close button).

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
8ffea9d5c5 workspace: Make title of overlay reactive
Also make the title of the overlay reactive so we can keep the overlay
visible if the mouse is hovering over the title.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Jonas Dreßler
4f3c8b8d69 workspace: Continue overlay idle hide timeout when pointing at close button
While it makes sense to remove the timeout in every other case, restart it
if the pointer is hovering over the close button to make sure the overlay
will be hidden afterwards.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/683
2019-09-18 15:56:26 +00:00
Kjartan Maraas
edf6bd6909 Update Norwegian Bokmål translation 2019-09-18 13:34:34 +00:00
Charles Monzat
3e58af10ca Update French translation 2019-09-17 18:47:13 +00:00
Alexandre Franke
9e55d262f9 Update French translation 2019-09-17 11:44:09 +00:00
Florian Müllner
252e694979 util: Handle trailing LTR/RTL markers in URLs
Some electron apps apparently spread those generously over their
notification text, so may sure to not include them accidentally
in URLs.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1614
2019-09-16 20:41:47 +00:00
Florian Müllner
efed695eca cleanup: Don't add linebreak before operators
When breaking overly long conditions into multiple lines, the operator
should end the previous line instead of starting the new one.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
b446667df6 cleanup: Disambiguate assignments in arrow functions
As arrow functions have an implicit return value, an assignment of
this.foo = bar could have been intended as a this.foo === bar
comparison. To catch those errors, we will disallow these kinds
of assignments unless they are marked explicitly by an extra pair
of parentheses.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
133a1e7bef cleanup: Remove trailing spaces
We generally avoid these (not least because Linus hates them enough
to make git complain loudly), but some sneaked in over time ...

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
5b3935fa43 cleanup: Fix up "special" comments
Our coding style asks for a space after the comment start, which
some of our ASCII-artsy comments violate. Adjust them to fit the
rule, or remove them altogether.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
471165ca9b cleanup: Use consistent brace style of blocks
Our coding style has always been to either put braces around all
blocks, or avoid them for all. Fix the couple of places that slipped
through.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
111f87a1b2 cleanup: Avoid pointless "renames" in destructuring
ES5 allows to rename variables in object destructuring, however this
only makes sense when we want to use a different name than the object
property.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
93525539c2 cleanup: Avoid unnecessary parentheses in arrow functions
Parentheses are only needed if there are zero or multiple arguments.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
a77377efe7 cleanup: Avoid useless return statements
Return statements are only useful if they return a value or break
the regular function flow (i.e. early returns). Remove all returns
that do neither.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
81ab2865f7 cleanup: Don't use Array/Object constructors
The corresponding literals are more concise and cleaner.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
e585f7d97b scripting: Disable an eslint warning
Calling await in a loop means the asynchronous operations are
run sequentially instead of in-parallel. Usually that's not
what's wanted, so eslint has a rule to warn about this.

However here we use async/await to handle control back to the
mainloop between steps, so running operations sequentially is
actually intended.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
1a32e3e74a volume: Clarify some code
We have more idiomatic ways to check whether any element fullfills
some condition than breaking out of a loop.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
8d6820c4df magnifier: Do not modify function argument
The intention of the code is clearly to operate on a copy, but that's
not how the Object constructor works. While it doesn't matter in
practice that we modify the passed-in object parameter, it's still
a good idea to fix the code.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
2546445884 magnifier: Simplify some code
We don't need nested if blocks to set or unset the crosshairs'
clip size.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/731
2019-09-15 16:02:45 +02:00
Florian Müllner
e44b7df078 lint: Drop extra ignored nodes in legacy config
They didn't just allow for the style patterns they were added to,
but allowed for some messed up indentation to slip through. Now
that we adapted the code to not use the old style, it's time to
drop the exceptions.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
3a9eaa39ea cleanup: Switch some method calls to new indentation style
The legacy indent rule currently ignores arrow functions in parameters
to allow callbacks to not align with the other arguments:

    this._someFunctionWithFairlyLongishName(arg1, arg2, arg3,
        () => {
            this._someOtherFunctionWithLongName(arg1);
        });

But as ignoring entire nodes means we can end up with arbitrary
indentation, we should drop the exception. While this would make
the above "illegal" under the legacy config, it conforms with the
non-legacy style, so everything should be fine ...

... except that eslint starts to complain about some function args
that should be fine under the legacy config. Maybe it's thrown off
by the function-arg-in-arrow-function-in-function-arg structure, but
rather than figuring it out, let's just move those to the new style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
af87bd8c87 cleanup: Use consistent style for ternary operator
We are currently inconsistent whether to put the operators in front
of the corresponding line or at the end of the preceding one. The
most dominant style for now is to put condition and first branch on
the same line, and then align the second branch:

  let foo = condition ? fooValue
                      : notFooValue;

Unfortunately that's a style that eslint doesn't support, so to account
for it, our legacy configuration currently plainly ignores all indentation
in conditionals.

In order to drop that exception and not let messed up indentation slip
through, change all ternary operators to the non-legacy style.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Florian Müllner
4bfb4a0e3d cleanup: Fix wrong indentation
Some more places where the indentation doesn't comply with either
the old or new style. They slipped through because the legacy eslint
configuration accounts for some patterns by plainly ignoring certain
nodes. We'll address that later, first fix up the indentation errors.

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/725
2019-09-15 13:30:19 +00:00
Martin Zurowietz
d1a6601e60 theme: Equalize dimensions of ws switcher popup boxes
The indicator for the active workspace is currently two pixels
smaller because it doesn't account for the border used for
inactive workspaces.

Fix that to make sure all indicators have the same size.

https://gitlab.gnome.org/GNOME/gnome-shell/issues/1243
2019-09-15 01:23:56 +02:00
Harshula Jayasuriya
817aec5466 overview: Fix fading out desktop icons
A typo in commit 0846238f69 broke the animation.

Signed-off-by: Harshula Jayasuriya <harshula@hj.id.au>

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

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

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

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

Only animate visible icons with opacity greater than 0.

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

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

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

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

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

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

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

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

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

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

    let foo = Object.create(null);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

When deserialised in GJS, we get:

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

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

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

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

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

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

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

https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/689
2019-09-01 12:45:49 +02:00
Changwoo Ryu
89f9925208 Update Korean translation 2019-09-01 09:00:28 +00:00
A S Alam
fcc1d7beff Update Punjabi translation 2019-08-31 13:45:30 +00:00
163 changed files with 26503 additions and 12888 deletions

View File

@@ -54,7 +54,7 @@ build:
- meson mutter mutter/build --prefix=/usr -Dtests=false
- ninja -C mutter/build install
script:
- meson . build -Dbuiltype=debugoptimized -Dman=false
- meson . build -Dbuiltype=debugoptimized -Dman=false --werror
- ninja -C build
- ninja -C build install
<<: *only_default

View File

@@ -1,6 +1,5 @@
#!/usr/bin/bash
shell_branch=$(git describe --contains --all HEAD)
mutter_target=
git clone https://gitlab.gnome.org/GNOME/mutter.git
@@ -26,8 +25,7 @@ if [ "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME" ]; then
fi
if [ -z "$mutter_target" ]; then
mutter_target=$(git branch -r -l origin/$shell_branch)
mutter_target=${mutter_target:-$(git branch -r -l ${shell_branch#remotes/})}
mutter_target=$(git branch -r -l origin/$CI_COMMIT_REF_NAME)
mutter_target=${mutter_target:-origin/master}
echo Using $mutter_target instead
fi

View File

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

150
NEWS
View File

@@ -1,3 +1,153 @@
3.34.5
======
* Leave overview when locking the screen [Jonas D.; !1043]
* Avoid IO on the main thread [Christian; !1050]
* Fix OSK layout fallback for unsupported variants [Florian; #2471]
* Fix high-contrast/symbolic icon mix-up [Florian; #2414]
* Misc. bug fixes and cleanups [Jonas Å., Florian; !1032, #2386]
Contributors:
Jonas Dreßler, Christian Hergert, Florian Müllner, Jwtiyar Nariman,
Jonas Ådahl
Translators:
Jwtiyar Nariman [ckb]
3.34.4
======
* Switch screen-recorder back to VP8 [Björn; #256]
Contributors:
Björn Daase
Translators:
Jor Teron [mjw], Dušan Kazik [sk]
3.34.3
======
* polkitAgent: Fix confirming via keyboard when password-less [Jonas; #2066]
* Misc. bug fixes and cleanups [Florian; !906]
Contributors:
Jonas Dreßler, Florian Müllner
3.34.2
======
* Fix unredirection after cancelled animations [Florian; #1788]
* Use cached coordinates for window sorting in overview [Andrew; !763]
* Include shadow in window screenshots [Robert; !762]
* Use correct timezones for events [Milan, Florian; !806, #1895]
* Adjust style of system menu action buttons [monday; !802]
* Fix windows getting stuck on screen if closed while animating [Florian; !815]
* Hide stopped spinner in top bar [Joonas; !834]
* Reuse existing icons when updating the app picker grid [Georges; !841]
* Fix not-responding dialog size when using geometry scaling [Jonas; !783]
* Fix battery icon glitch in "100% but charging" case [Philip; !814]
* Update window titles in app menu [Florian; #1830]
* Improve modifier-less keyboard navigation of switcher popups [Florian; #1883]
* Use better OSK layout fallback for unsupported variants [Florian; #1907]
* Fix creating app folders with no pre-existing folders [Jonas; #1652]
* Improve DND page switching in app picker [Florian, Jonas; #1693]
* Show polkit confirmation dialog for users with no password [Joaquim; !829]
* Fix interacting with applications when magnifier is enabled [Jonas; !754]
* Tweak styling of notifications/media constrols [Joonas; !855, !865]
* Fix disable command of gnome-extensions tool [Florian; #1946]
* Enable clean session shutdown after gnome-shell failure [Benjamin; !858]
* Also remove scaled keys when texture cache is cleared [Daniel; !567]
* Don't show overflow indicator in switchers that fit screen [Florian; #1834]
* Place launched applications into a systemd scope [Benjamin; !863]
* Fix weather forecasts for automatic location when Weather is not sandboxed
[Florian; #1823]
* Dismiss switcher popups when a system modal dialogs opens [Florian; #1536]
* Misc. bug fixes and cleanups [Marco, Philip, Florian, cunidev, Jonas, Joonas;
!758, !749, !777, !811, #1884, !823, !840, !782, !847, #1836, !852, !851,
!788, #1916, !866, !884]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Philip Chimento, Milan Crha,
Jonas Dreßler, Joonas Henriksson, Robert Mader, Daniel García Moreno,
Florian Müllner, Georges Basile Stavracas Neto, Joaquim Rocha, Andrew Watson,
cunidev, monday
Translators:
Stas Solovey [ru], Ricardo Silva Veloso [pt_BR], Yi-Jyun Pan [zh_TW],
Umarzuki Bin Mochlis Moktar [ms]
3.34.1
======
* Fix "Frequent" view icons disappearing on hover [Jonas D.; #1502]
* Allow editing app folder names [Georges, Marco; !675, !720]
* Skip property transitions while hidden [Florian; !708]
* Make menu animations more consistent [Florian, GB_2; #1595, !717]
* Improve performance when enabling/disabling all extensions [Jonas D.; !96]
* Fix extra icons appearing in "Frequent" view animation [Georges; !696]
* Fix fading out desktop icons [Harshula; #1616]
* Fix box-shadow glitch with prerendered resources [Daniel; #1186]
* Fix accidentally skipped animations [Florian; #1572]
* Fix screenshots and window animations when scaled [Robert; !728]
* Don't leak NOTIFY_SOCKET environment variable to applications [Benjamin; !741]
* Fix lock-up on X11 when ibus is already running on startup [Marco; #1712]
* Fix screen dimming on idle [Marco; #1683]
* Do not notify systemd before initialization is complete [Iain; !750]
* Support SAE secrets in network agent [Lubomir; !751]
* Fix various regressions with dynamic workspaces [Florian; #1497]
* Fixed crashes [Florian, Marco; #1678, !746]
* Misc. bug fixes and cleanups [Marco, Jonas D., Florian, Iain, Georges,
Jonas Å., Martin, Takao, Carlos; !700, !705, !709, !711, !707, #1538, !710,
!713, !699, !715, !718, !716, !719, !721, #1243, !725, !731, #1614, !683,
!732, !121, !735, !736, !740, #573, #1641, #1571]
Contributors:
Marco Trevisan (Treviño), Benjamin Berg, Jonas Dreßler, Takao Fujiwara, GB_2,
Carlos Garnacho, Harshula Jayasuriya, Iain Lane, Robert Mader,
Daniel García Moreno, Florian Müllner, Georges Basile Stavracas Neto,
Lubomir Rintel, Martin Zurowietz, Jonas Ådahl
Translators:
Rafael Fontenelle [pt_BR], Fran Dieguez [gl], Balázs Úr [hu],
Milo Casagrande [it], Daniel Șerbănescu [ro], Kukuh Syafaat [id],
Jiri Grönroos [fi], Daniel Mustieles [es], Piotr Drąg [pl],
Anders Jonsson [sv], Marek Černocký [cs], Jordi Mas [ca],
Aurimas Černius [lt], Christian Kirbach [de], Emin Tufan Çetin [tr],
Enrico Nicoletto [pt_BR], Danial Behzadi [fa], Марко Костић [sr],
Alexandre Franke [fr], Charles Monzat [fr], Kjartan Maraas [nb],
Ryuta Fujii [ja], Nathan Follens [nl], Dušan Kazik [sk], Fabio Tomat [fur],
Matej Urbančič [sl], Ask Hjorth Larsen [da], Alan Mortensen [da]
3.34.0
======
* Handle startup/shutdown of misc X11 services [Carlos; !680]
* Fix sound volume mute/unmute [Iain; #1557]
* Correctly terminate pasted text [Carlos; #1570]
Contributors:
Carlos Garnacho, Iain Lane
Translators:
Tom Tryfonidis [el], Milo Casagrande [it], Ryuta Fujii [ja],
Efstathios Iosifidis [el], Carmen Bianca BAKKER [eo], Sabri Ünal [tr],
Dušan Kazik [sk], Balázs Meskó [hu], Claude Paroz [fr]
3.33.92
=======
* Animate pointer a11y pie timer [Jonas D.; !688]
* Fix restarting shell in systemd user session [Benjamin; !690]
* Misc. bug fixes and cleanups [Florian, Jonas D., Jonas Å., Will;
!691, !689, !692, #1552, !698]
Contributors:
Jonas Ådahl, Benjamin Berg, Piotr Drąg, Jonas Dreßler, Florian Müllner,
Will Thompson
Translators:
Daniel Șerbănescu [ro], Danial Behzadi [fa], Daniel Mustieles [es],
Jiri Grönroos [fi], Asier Sarasua Garmendia [eu], Piotr Drąg [pl],
Rūdolfs Mazurs [lv], Anders Jonsson [sv], Fran Dieguez [gl], Jordi Mas [ca],
Matej Urbančič [sl], Zander Brown [en_GB], Ryuta Fujii [ja], Tim Sabsch [de],
Fabio Tomat [fur], Pawan Chitrakar [ne], A S Alam [pa], Changwoo Ryu [ko],
Aurimas Černius [lt], Daniel Rusek [cs], Marek Černocký [cs],
Kukuh Syafaat [id], Goran Vidović [hr], Rafael Fontenelle [pt_BR]
3.33.91
=======
* Fix regression when adjusting brightness [Florian; #1500]

View File

@@ -30,3 +30,6 @@
/* Define if fdwalk is available in libc */
#mesondefine HAVE_FDWALK
/* Define if we have gnome-desktop systemd utils */
#mesondefine HAVE_GNOME_SYSTEMD

View File

@@ -1,11 +1,12 @@
[Unit]
Description=Disable GNOME Shell extensions after failure
# Note that this unit must not conflict with anything, and must
# be able to run in parallel with the gnome-session-shutdown.target.
DefaultDependencies=no
# Only disable extensions for a short period of time after login.
# This means we err on the side of failing the first login after a broken
# extension was installed.
Requisite=gnome-session-stable.timer
# We want to disable extensions only if gnome-shell has flagged the extensions
# to be a likely cause of trouble.
ConditionPathExists=%t/gnome-shell-disable-extensions
[Service]
Type=simple

View File

@@ -23,3 +23,5 @@ ExecStart=@bindir@/gnome-shell
SuccessExitStatus=1
# On wayland we cannot restart
Restart=no
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -29,3 +29,5 @@ SuccessExitStatus=1
Restart=always
# Do not wait before restarting the shell
RestartSec=0ms
# Kill any stubborn child processes after this long
TimeoutStopSec=5

View File

@@ -610,6 +610,13 @@ StScrollBar {
border-bottom-style: solid;
}
// Rename popup
.rename-folder-popup {
.rename-folder-popup-item {
spacing: 6px;
&:ltr, &:rtl { padding: 0, 12px; }
}
}
// Background menu
.background-menu { -boxpointer-gap: 4px; -arrow-rise: 0px; }
@@ -742,7 +749,7 @@ StScrollBar {
.ws-switcher-active-up, .ws-switcher-active-down,
.ws-switcher-active-left, .ws-switcher-active-right {
height: 50px;
height: 52px;
background-color: $selected_bg_color;
color: $selected_fg_color;
background-size: 32px;
@@ -1054,9 +1061,9 @@ StScrollBar {
}
.calendar-today {
font-weight: bold;
//color: lighten($fg_color,10%);
//background-color: darken($bg_color,5%);
border: 1px solid $_bubble_borders_color;
color: lighten($fg_color,5%);
background-color: darken($bg_color,5%);
// border: 1px solid lighten($_bubble_borders_color,20%);
}
.calendar-day-with-events {
color: lighten($fg_color,10%);
@@ -1146,14 +1153,21 @@ StScrollBar {
padding: 10px;
}
.message-close-button {
color: lighten($fg_color, 15%);
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
}
.message-media-control {
padding: 12px;
color: lighten($fg_color, 15%);
&:last-child:ltr { padding-right: 18px; }
&:last-child:rtl { padding-left: 18px; }
&:hover { color: $fg_color; }
&:insensitive { color: darken($fg_color,40%); }
&:hover { color: if($variant=='light', lighten($fg_color, 30%), darken($fg_color, 10%)); }
&:active { color: if($variant=='light', lighten($fg_color, 40%), darken($fg_color, 20%)); }
&:insensitive { color: if($variant=='light', lighten($fg_color, 50%), darken($fg_color, 40%)); }
}
.media-message-cover-icon {
@@ -1202,12 +1216,11 @@ StScrollBar {
&:hover, &:focus {
background-color: $_hover_bg_color;
color: $fg_color;
border: none;
padding: 14px;
}
&:active {
background-color: $selected_bg_color;
color: $selected_fg_color;
border-color: $selected_borders_color;
}
& > StIcon { icon-size: 16px; }

View File

@@ -285,8 +285,9 @@ var Application = GObject.registerClass({
log(`Failed to connect to shell proxy: ${e}`);
this._mainStack.add_named(new NoShellPlaceholder(), 'noshell');
this._mainStack.visible_child_name = 'noshell';
} else
} else {
throw e;
}
return;
}
@@ -567,6 +568,10 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._extension = extension;
this._prefsModule = null;
this.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
this._extensionStateChangedId = this._app.shellProxy.connectSignal(
'ExtensionStateChanged', (p, sender, [uuid, newState]) => {
if (this.uuid !== uuid)
@@ -574,13 +579,13 @@ class ExtensionRow extends Gtk.ListBoxRow {
this._extension = ExtensionUtils.deserializeExtension(newState);
let state = (this._extension.state == ExtensionState.ENABLED);
GObject.signal_handler_block(this._switch, this._notifyActiveId);
this._switch.state = state;
GObject.signal_handler_unblock(this._switch, this._notifyActiveId);
this._switch.sensitive = this._canToggle();
});
this.connect('destroy', this._onDestroy.bind(this));
this._buildUI();
}
get uuid() {
@@ -646,7 +651,7 @@ class ExtensionRow extends Gtk.ListBoxRow {
sensitive: this._canToggle(),
state: this._extension.state === ExtensionState.ENABLED
});
this._switch.connect('notify::active', () => {
this._notifyActiveId = this._switch.connect('notify::active', () => {
if (this._switch.active)
this._app.shellProxy.EnableExtensionRemote(this.uuid);
else

View File

@@ -202,7 +202,6 @@ var ConsecutiveBatch = class extends Batch {
hold.disconnect(signalId);
this.nextTask();
});
return;
} else {
// This task finished, process the next one
this.nextTask();

View File

@@ -921,7 +921,7 @@ var LoginDialog = GObject.registerClass({
return;
this._bindOpacity();
this.actor.ease({
this.ease({
opacity: 255,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
@@ -944,7 +944,7 @@ var LoginDialog = GObject.registerClass({
_startSession(serviceName) {
this._bindOpacity();
this.actor.ease({
this.ease({
opacity: 0,
duration: _FADE_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,

View File

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

View File

@@ -15,6 +15,5 @@ var LOCALEDIR = '@datadir@/locale';
/* other standard directories */
var LIBEXECDIR = '@libexecdir@';
var PKGDATADIR = '@datadir@/@PACKAGE_NAME@';
var VPNDIR = '@vpndir@';
/* g-i package versions */
var LIBMUTTER_API_VERSION = '@LIBMUTTER_API_VERSION@'

View File

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

View File

@@ -28,7 +28,7 @@ var HistoryManager = class {
this._entry = params.entry;
if (this._entry) {
this._entry.connect('key-press-event',
this._entry.connect('key-press-event',
this._onEntryKeyPress.bind(this));
}
}

View File

@@ -2,7 +2,6 @@
/* exported getIBusManager */
const { Gio, GLib, IBus } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const IBusCandidatePopup = imports.ui.ibusCandidatePopup;
@@ -19,9 +18,9 @@ function _checkIBusVersion(requiredMajor, requiredMinor, requiredMicro) {
IBus.MICRO_VERSION >= requiredMicro))
return;
throw "Found IBus version %d.%d.%d but required is %d.%d.%d".
format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
throw "Found IBus version %d.%d.%d but required is %d.%d.%d"
.format(IBus.MAJOR_VERSION, IBus.MINOR_VERSION, IBus.MINOR_VERSION,
requiredMajor, requiredMinor, requiredMicro);
}
function getIBusManager() {
@@ -59,16 +58,30 @@ var IBusManager = class {
this._spawn();
}
_spawn() {
_spawn(extraArgs = []) {
try {
Gio.Subprocess.new(['ibus-daemon', '--xim', '--panel', 'disable'],
Gio.SubprocessFlags.NONE);
let cmdLine = ['ibus-daemon', '--panel', 'disable', ...extraArgs];
Gio.Subprocess.new(cmdLine, Gio.SubprocessFlags.NONE);
} catch (e) {
log(`Failed to launch ibus-daemon: ${e.message}`);
}
}
restartDaemon(extraArgs = []) {
this._spawn(['-r', ...extraArgs]);
}
_clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
if (this._preloadEnginesId) {
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
if (this._panelService)
this._panelService.destroy();
@@ -80,33 +93,44 @@ var IBusManager = class {
this._currentEngineName = null;
this.emit('ready', false);
this._spawn();
}
_onConnected() {
this._ibus.list_engines_async(-1, null, this._initEngines.bind(this));
this._cancellable = new Gio.Cancellable();
this._ibus.list_engines_async(-1, this._cancellable,
this._initEngines.bind(this));
this._ibus.request_name_async(IBus.SERVICE_PANEL,
IBus.BusNameFlag.REPLACE_EXISTING,
-1, null,
this._initPanelService.bind(this));
IBus.BusNameFlag.REPLACE_EXISTING, -1, this._cancellable,
this._initPanelService.bind(this));
}
_initEngines(ibus, result) {
let enginesList = this._ibus.list_engines_async_finish(result);
if (enginesList) {
try {
let enginesList = this._ibus.list_engines_async_finish(result);
for (let i = 0; i < enginesList.length; ++i) {
let name = enginesList[i].get_name();
this._engines.set(name, enginesList[i]);
}
this._updateReadiness();
} else {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
this._clear();
}
}
_initPanelService(ibus, result) {
let success = this._ibus.request_name_async_finish(result);
let success = false;
try {
success = !!this._ibus.request_name_async_finish(result);
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
return;
logError(e);
}
if (success) {
this._panelService = new IBus.PanelService({ connection: this._ibus.get_connection(),
object_path: IBus.PATH_PANEL });
@@ -133,7 +157,7 @@ var IBusManager = class {
} catch (e) {
}
// If an engine is already active we need to get its properties
this._ibus.get_global_engine_async(-1, null, (i, result) => {
this._ibus.get_global_engine_async(-1, this._cancellable, (_bus, result) => {
let engine;
try {
engine = this._ibus.get_global_engine_async_finish(result);
@@ -205,8 +229,18 @@ var IBusManager = class {
return;
}
this._ibus.set_global_engine_async(id, this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
null, callback || null);
this._ibus.set_global_engine_async(id,
this._MAX_INPUT_SOURCE_ACTIVATION_TIME,
this._cancellable, (_bus, res) => {
try {
this._ibus.set_global_engine_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
logError(e);
}
if (callback)
callback();
});
}
preloadEngines(ids) {
@@ -214,21 +248,23 @@ var IBusManager = class {
return;
if (this._preloadEnginesId != 0) {
Mainloop.source_remove(this._preloadEnginesId);
GLib.source_remove(this._preloadEnginesId);
this._preloadEnginesId = 0;
}
this._preloadEnginesId =
Mainloop.timeout_add_seconds(this._PRELOAD_ENGINES_DELAY_TIME,
() => {
this._ibus.preload_engines_async(
ids,
-1,
null,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
this._PRELOAD_ENGINES_DELAY_TIME,
() => {
this._ibus.preload_engines_async(
ids,
-1,
this._cancellable,
null);
this._preloadEnginesId = 0;
return GLib.SOURCE_REMOVE;
});
}
};
Signals.addSignalMethods(IBusManager.prototype);

View File

@@ -1,6 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported InputMethod */
const { Clutter, GLib, GObject, IBus } = imports.gi;
const { Clutter, GLib, Gio, GObject, IBus } = imports.gi;
const Keyboard = imports.ui.status.keyboard;
@@ -36,15 +36,7 @@ class InputMethod extends Clutter.InputMethod {
}
_updateCapabilities() {
let caps = 0;
if (this.can_show_preedit)
caps |= IBus.Capabilite.PREEDIT_TEXT;
if (this._currentFocus)
caps |= IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
else
caps |= IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.AUXILIARY_TEXT | IBus.Capabilite.LOOKUP_TABLE | IBus.Capabilite.PROPERTY;
let caps = IBus.Capabilite.PREEDIT_TEXT | IBus.Capabilite.FOCUS | IBus.Capabilite.SURROUNDING_TEXT;
if (this._context)
this._context.set_capabilities(caps);
@@ -55,12 +47,22 @@ class InputMethod extends Clutter.InputMethod {
}
_onConnected() {
this._ibus.create_input_context_async ('gnome-shell', -1, null,
this._setContext.bind(this));
this._cancellable = new Gio.Cancellable();
this._ibus.create_input_context_async ('gnome-shell', -1,
this._cancellable, this._setContext.bind(this));
}
_setContext(bus, res) {
this._context = this._ibus.create_input_context_async_finish(res);
try {
this._context = this._ibus.create_input_context_async_finish(res);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
logError(e);
this._clear();
}
return;
}
this._context.connect('commit-text', this._onCommitText.bind(this));
this._context.connect('delete-surrounding-text', this._onDeleteSurroundingText.bind(this));
this._context.connect('update-preedit-text', this._onUpdatePreeditText.bind(this));
@@ -72,6 +74,11 @@ class InputMethod extends Clutter.InputMethod {
}
_clear() {
if (this._cancellable) {
this._cancellable.cancel();
this._cancellable = null;
}
this._context = null;
this._hints = 0;
this._purpose = 0;
@@ -137,7 +144,6 @@ class InputMethod extends Clutter.InputMethod {
this._currentFocus = focus;
if (this._context) {
this._context.focus_in();
this._updateCapabilities();
this._emitRequestSurrounding();
}
@@ -149,10 +155,8 @@ class InputMethod extends Clutter.InputMethod {
vfunc_focus_out() {
this._currentFocus = null;
if (this._context) {
if (this._context)
this._context.focus_out();
this._updateCapabilities();
}
if (this._preeditStr) {
// Unset any preedit text
@@ -255,17 +259,19 @@ class InputMethod extends Clutter.InputMethod {
if (event.type() == Clutter.EventType.KEY_RELEASE)
state |= IBus.ModifierType.RELEASE_MASK;
this._context.process_key_event_async(event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, null,
(context, res) => {
try {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);
} catch (e) {
log(`Error processing key on IM: ${e.message}`);
}
});
this._context.process_key_event_async(
event.get_key_symbol(),
event.get_key_code() - 8, // Convert XKB keycodes to evcodes
state, -1, this._cancellable,
(context, res) => {
try {
let retval = context.process_key_event_async_finish(res);
this.notify_key_event(event, retval);
} catch (e) {
if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
log(`Error processing key on IM: ${e.message}`);
}
});
return true;
}
});

View File

@@ -40,6 +40,15 @@ var IntrospectService = class {
});
this._syncRunningApplications();
this._whitelistMap = new Map();
APP_WHITELIST.forEach(appName => {
Gio.DBus.watch_name(Gio.BusType.SESSION,
appName,
Gio.BusNameWatcherFlags.NONE,
(conn, name, owner) => this._whitelistMap.set(name, owner),
(conn, name) => this._whitelistMap.delete(name));
});
}
_isStandaloneApp(app) {
@@ -51,7 +60,7 @@ var IntrospectService = class {
}
_isSenderWhitelisted(sender) {
return APP_WHITELIST.includes(sender);
return [...this._whitelistMap.values()].includes(sender);
}
_getSandboxedAppId(app) {
@@ -127,7 +136,8 @@ var IntrospectService = class {
let apps = this._appSystem.get_running();
let windowsList = {};
if (!this._isIntrospectEnabled()) {
if (!this._isIntrospectEnabled() &&
!this._isSenderWhitelisted(invocation.get_sender())) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');

View File

@@ -172,7 +172,7 @@ function getPropertyNamesFromExpression(expr, commandHeader = '') {
// Make sure propsUnique contains one key for every
// property so we end up with a unique list of properties
allProps.map(p => propsUnique[p] = null);
allProps.map(p => (propsUnique[p] = null));
}
return Object.keys(propsUnique).sort();
}
@@ -217,7 +217,7 @@ function isUnsafeExpression(str) {
prunedStr = prunedStr.replace(/[=!]==/g, ''); //replace === and !== with nothing
prunedStr = prunedStr.replace(/[=<>!]=/g, ''); //replace ==, <=, >=, != with nothing
if (prunedStr.match(/=/)) {
if (prunedStr.match(/[=]/)) {
return true;
} else if (prunedStr.match(/;/)) {
// If we contain a semicolon not inside of a quote/regex, assume we're unsafe as well

View File

@@ -7,7 +7,6 @@ jsconf.set10('HAVE_BLUETOOTH', bt_dep.found())
jsconf.set10('HAVE_NETWORKMANAGER', have_networkmanager)
jsconf.set('datadir', datadir)
jsconf.set('libexecdir', libexecdir)
jsconf.set('vpndir', vpndir)
config_js = configure_file(
input: 'config.js.in',

View File

@@ -84,9 +84,9 @@ function _findProviderForSid(sid) {
}
//------------------------------------------------------------------------------
// Support for the old ModemManager interface (MM < 0.7)
//------------------------------------------------------------------------------
// ----------------------------------------------------- //
// Support for the old ModemManager interface (MM < 0.7) //
// ----------------------------------------------------- //
// The following are not the complete interfaces, just the methods we need
@@ -182,9 +182,9 @@ var ModemCdma = class {
Signals.addSignalMethods(ModemCdma.prototype);
//------------------------------------------------------------------------------
// Support for the new ModemManager1 interface (MM >= 0.7)
//------------------------------------------------------------------------------
// ------------------------------------------------------- //
// Support for the new ModemManager1 interface (MM >= 0.7) //
// ------------------------------------------------------- //
const BroadbandModemInterface = loadInterfaceXML('org.freedesktop.ModemManager1.Modem');
const BroadbandModemProxy = Gio.DBusProxy.makeProxyWrapper(BroadbandModemInterface);

View File

@@ -244,8 +244,9 @@ const SystemActions = GObject.registerClass({
_updateOrientationLockIcon() {
let locked = this._orientationSettings.get_boolean('orientation-lock');
let iconName = locked ? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic';
let iconName = locked
? 'rotation-locked-symbolic'
: 'rotation-allowed-symbolic';
this._actions.get(LOCK_ORIENTATION_ACTION_ID).iconName = iconName;
this.notify('orientation-lock-icon');
@@ -268,7 +269,7 @@ const SystemActions = GObject.registerClass({
getMatchingActions(terms) {
// terms is a list of strings
terms = terms.map((term) => term.toLowerCase());
terms = terms.map(term => term.toLowerCase());
let results = [];

View File

@@ -3,9 +3,8 @@
formatTime, formatTimeSpan, createTimeLabel, insertSorted,
makeCloseButton, ensureActorVisibleInScrollView */
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Shell, St, GnomeDesktop } = imports.gi;
const Gettext = imports.gettext;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Params = imports.misc.params;
@@ -15,7 +14,7 @@ var SCROLL_TIME = 100;
// http://daringfireball.net/2010/07/improved_regex_for_matching_urls
const _balancedParens = '\\([^\\s()<>]+\\)';
const _leadingJunk = '[\\s`(\\[{\'\\"<\u00AB\u201C\u2018]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u201C\u201D\u2018\u2019]';
const _notTrailingJunk = '[^\\s`!()\\[\\]{};:\'\\".,<>?\u00AB\u00BB\u200E\u200F\u201C\u201D\u2018\u2019\u202A\u202C]';
const _urlRegexp = new RegExp(
`(^|${_leadingJunk})` +
@@ -128,6 +127,14 @@ function trySpawn(argv) {
throw err;
}
}
// Async call, we don't need the reply though
try {
GnomeDesktop.start_systemd_scope(argv[0], pid, null, null, null, () => {});
} catch (err) {
// Ignore error; it likely means GnomeDesktop is too old
}
// Dummy child watch; we don't want to double-fork internally
// because then we lose the parent-child relationship, which
// can break polkit. See https://bugzilla.redhat.com//show_bug.cgi?id=819275
@@ -314,7 +321,8 @@ function lowerBound(array, val, cmp) {
if (array.length == 0)
return 0;
min = 0; max = array.length;
min = 0;
max = array.length;
while (min < (max - 1)) {
mid = Math.floor((min + max) / 2);
v = cmp(array[mid], val);

View File

@@ -32,6 +32,7 @@ var WeatherClient = class {
this._gclueStarting = false;
this._gclueLocationChangedId = 0;
this._needsAuth = true;
this._weatherAuthorized = false;
this._permStore = new PermissionStore.PermissionStore((proxy, error) => {
if (error) {
@@ -142,7 +143,7 @@ var WeatherClient = class {
get _useAutoLocation() {
return this._autoLocationRequested &&
this._locationSettings.get_boolean('enabled') &&
this._weatherAuthorized;
(!this._needsAuth || this._weatherAuthorized);
}
_onWeatherProxyReady(o, res) {
@@ -175,6 +176,13 @@ var WeatherClient = class {
if (hadApp !== haveApp)
this.emit('changed');
let neededAuth = this._needsAuth;
this._needsAuth = this._weatherApp === null ||
this._weatherApp.app_info.has_key('X-Flatpak');
if (neededAuth !== this._needsAuth)
this._updateAutoLocation();
}
_loadInfo() {

View File

@@ -57,7 +57,7 @@ function waitAndDraw(milliseconds) {
cb();
});
return callback => cb = callback;
return callback => (cb = callback);
}
function waitSignal(object, signal) {
@@ -69,7 +69,7 @@ function waitSignal(object, signal) {
cb();
});
return callback => cb = callback;
return callback => (cb = callback);
}
function extractBootTimestamp() {
@@ -137,9 +137,9 @@ function *run() {
Main.overview.hide();
yield Scripting.waitLeisure();
////////////////////////////////////////
// Tests of redraw speed
////////////////////////////////////////
// --------------------- //
// Tests of redraw speed //
// --------------------- //
global.frame_timestamps = true;
global.frame_finish_timestamp = true;
@@ -186,8 +186,6 @@ function *run() {
yield Scripting.sleep(1000);
////////////////////////////////////////
let appSys = Shell.AppSystem.get_default();
let app = appSys.lookup_app('org.gnome.gedit.desktop');

View File

@@ -147,7 +147,7 @@ var AccessDialogDBus = class {
subtitle, body, options);
dialog.open();
dialog.connect('closed', () => this._accessDialog = null);
dialog.connect('closed', () => (this._accessDialog = null));
this._accessDialog = dialog;
}

View File

@@ -3,7 +3,6 @@
WindowCyclerPopup */
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const SwitcherPopup = imports.ui.switcherPopup;
@@ -292,7 +291,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
if (this._thumbnails)
this._destroyThumbnails();
if (this._thumbnailTimeoutId != 0)
Mainloop.source_remove(this._thumbnailTimeoutId);
GLib.source_remove(this._thumbnailTimeoutId);
}
/**
@@ -327,7 +326,7 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
}
if (this._thumbnailTimeoutId != 0) {
Mainloop.source_remove(this._thumbnailTimeoutId);
GLib.source_remove(this._thumbnailTimeoutId);
this._thumbnailTimeoutId = 0;
}
@@ -344,7 +343,8 @@ class AppSwitcherPopup extends SwitcherPopup.SwitcherPopup {
this._thumbnails.highlight(window, forceAppFocus);
} else if (this._items[this._selectedIndex].cachedWindows.length > 1 &&
!forceAppFocus) {
this._thumbnailTimeoutId = Mainloop.timeout_add (
this._thumbnailTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
THUMBNAIL_POPUP_TIME,
this._timeoutPopupThumbnails.bind(this));
GLib.Source.set_name_by_id(this._thumbnailTimeoutId, '[gnome-shell] this._timeoutPopupThumbnails');
@@ -437,8 +437,8 @@ class CyclerHighlight {
if (this._clone.source)
this._clone.source.sync_visibility();
let windowActor = this._window ? this._window.get_compositor_private()
: null;
let windowActor = this._window
? this._window.get_compositor_private() : null;
if (windowActor)
windowActor.hide();
@@ -648,8 +648,9 @@ class WindowCyclerPopup extends CyclerPopup {
}
});
var AppIcon = GObject.registerClass(
class AppIcon extends St.BoxLayout {
var AppIcon = GObject.registerClass({
GTypeName: 'AltTab_AppIcon'
}, class AppIcon extends St.BoxLayout {
_init(app) {
super._init({ style_class: 'alt-tab-app',
vertical: true });
@@ -711,7 +712,7 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
_onDestroy() {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
GLib.source_remove(this._mouseTimeOutId);
this.icons.forEach(icon => {
icon.app.disconnect(icon._stateChangedId);
@@ -790,14 +791,16 @@ class AppSwitcher extends SwitcherPopup.SwitcherList {
// activation when the thumbnail list is open
_onItemEnter(index) {
if (this._mouseTimeOutId != 0)
Mainloop.source_remove(this._mouseTimeOutId);
GLib.source_remove(this._mouseTimeOutId);
if (this._altTabPopup.thumbnailsVisible) {
this._mouseTimeOutId = Mainloop.timeout_add(APP_ICON_HOVER_TIMEOUT,
() => {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
});
this._mouseTimeOutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
APP_ICON_HOVER_TIMEOUT,
() => {
this._enterItem(index);
this._mouseTimeOutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._mouseTimeOutId, '[gnome-shell] this._enterItem');
} else {
this._itemEntered(index);
@@ -874,9 +877,9 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
_init(windows) {
super._init(false);
this._labels = new Array();
this._thumbnailBins = new Array();
this._clones = new Array();
this._labels = [];
this._thumbnailBins = [];
this._clones = [];
this._windows = windows;
for (let i = 0; i < windows.length; i++) {
@@ -937,7 +940,7 @@ class ThumbnailList extends SwitcherPopup.SwitcherList {
}
// Make sure we only do this once
this._thumbnailBins = new Array();
this._thumbnailBins = [];
}
_removeThumbnail(source, clone) {
@@ -1011,9 +1014,9 @@ class WindowIcon extends St.BoxLayout {
}
_createAppIcon(app, size) {
let appIcon = app ? app.create_icon_texture(size)
: new St.Icon({ icon_name: 'icon-missing',
icon_size: size });
let appIcon = app
? app.create_icon_texture(size)
: new St.Icon({ icon_name: 'icon-missing', icon_size: size });
appIcon.x_expand = appIcon.y_expand = true;
appIcon.x_align = appIcon.y_align = Clutter.ActorAlign.END;
@@ -1040,7 +1043,7 @@ class WindowList extends SwitcherPopup.SwitcherList {
this.addItem(icon, icon.label);
this.icons.push(icon);
icon._unmanagedSignalId = icon.window.connect('unmanaged', (window) => {
icon._unmanagedSignalId = icon.window.connect('unmanaged', window => {
this._removeWindow(window);
});
}

View File

@@ -2,7 +2,8 @@
/* exported Animation, AnimatedIcon, Spinner */
const { Clutter, GLib, Gio, St } = imports.gi;
const Mainloop = imports.mainloop;
const Params = imports.misc.params;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300;
@@ -45,7 +46,7 @@ var Animation = class {
stop() {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
@@ -54,12 +55,19 @@ var Animation = class {
_loadFile(file, width, height) {
let [validResourceScale, resourceScale] = this.actor.get_resource_scale();
let wasPlaying = this._isPlaying;
if (this._isPlaying)
this.stop();
this._isLoaded = false;
this.actor.destroy_all_children();
if (!validResourceScale)
if (!validResourceScale) {
if (wasPlaying)
this.play();
return;
}
let textureCache = St.TextureCache.get_default();
let scaleFactor = St.ThemeContext.get_for_stage(global.stage).scale_factor;
@@ -67,6 +75,9 @@ var Animation = class {
scaleFactor, resourceScale,
this._animationsLoaded.bind(this));
this.actor.set_child(this._animations);
if (wasPlaying)
this.play();
}
_showFrame(frame) {
@@ -122,12 +133,22 @@ var AnimatedIcon = class extends Animation {
};
var Spinner = class extends AnimatedIcon {
constructor(size, animate = false) {
constructor(size, params) {
// Compatibility with older callers
if (params === true || params === false)
params = { animate: params };
params = Params.parse(params, {
animate: false,
hideOnStop: false,
});
let file = Gio.File.new_for_uri('resource:///org/gnome/shell/theme/process-working.svg');
super(file, size);
this.actor.opacity = 0;
this._animate = animate;
this._animate = params.animate;
this._hideOnStop = params.hideOnStop;
this.actor.visible = !this._hideOnStop;
}
_onDestroy() {
@@ -137,6 +158,7 @@ var Spinner = class extends AnimatedIcon {
play() {
this.actor.remove_all_transitions();
this.actor.show();
if (this._animate) {
super.play();
@@ -158,13 +180,20 @@ var Spinner = class extends AnimatedIcon {
if (this._animate) {
this.actor.ease({
opacity: 0,
time: SPINNER_ANIMATION_TIME,
transition: 'linear',
onComplete: () => super.stop()
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => {
super.stop();
if (this._hideOnStop)
this.actor.hide();
},
});
} else {
this.actor.opacity = 0;
super.stop();
if (this._hideOnStop)
this.actor.hide();
}
}
};

View File

@@ -3,7 +3,6 @@
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
const Mainloop = imports.mainloop;
const AppFavorites = imports.ui.appFavorites;
const BoxPointer = imports.ui.boxpointer;
@@ -41,6 +40,9 @@ var PAGE_SWITCH_TIME = 300;
var APP_ICON_SCALE_IN_TIME = 500;
var APP_ICON_SCALE_IN_DELAY = 700;
const OVERSHOOT_THRESHOLD = 20;
const OVERSHOOT_TIMEOUT = 1000;
const SWITCHEROO_BUS_NAME = 'net.hadess.SwitcherooControl';
const SWITCHEROO_OBJECT_PATH = '/net/hadess/SwitcherooControl';
@@ -98,7 +100,10 @@ function _findBestFolderName(apps) {
let commonCategories = [];
appInfos.reduce((categories, appInfo) => {
for (let category of appInfo.get_categories().split(';')) {
const appCategories = appInfo.get_categories();
if (!appCategories)
return categories;
for (let category of appCategories.split(';')) {
if (!(category in categoryCounter))
categoryCounter[category] = 0;
@@ -174,10 +179,11 @@ class BaseAppView {
// Remove old app icons
removedApps.forEach(icon => {
let iconIndex = this._allItems.indexOf(icon);
let id = icon.id;
this._allItems.splice(iconIndex, 1);
this._grid.removeItem(icon);
delete this._items[icon.id];
icon.actor.destroy();
delete this._items[id];
});
// Add new app icons
@@ -309,7 +315,12 @@ var AllView = class AllView extends BaseAppView {
this._grid.currentPage = 0;
this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._eventBlocker = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
visible: false,
});
this._stack.add_actor(this._eventBlocker);
box.add_actor(this._stack);
@@ -336,12 +347,16 @@ var AllView = class AllView extends BaseAppView {
});
this._eventBlocker.add_action(this._clickAction);
this._currentPopup = null;
this._displayingPopup = false;
this._currentPopupDestroyId = 0;
this._availWidth = 0;
this._availHeight = 0;
this._lastOvershootY = -1;
this._lastOvershootTimeoutId = 0;
Main.overview.connect('hidden', () => this.goToPage(0));
this._grid.connect('space-opened', () => {
let fadeEffect = this._scrollView.get_effect('fade');
@@ -378,8 +393,6 @@ var AllView = class AllView extends BaseAppView {
Main.overview.connect('item-drag-begin', this._onDragBegin.bind(this));
Main.overview.connect('item-drag-end', this._onDragEnd.bind(this));
this._nEventBlockerInhibits = 0;
}
_redisplay() {
@@ -426,7 +439,7 @@ var AllView = class AllView extends BaseAppView {
}
_loadApps() {
let newApps = [];
let appIcons = [];
this._appInfoList = Shell.AppSystem.get_default().get_installed().filter(appInfo => {
try {
(appInfo.get_id()); // catch invalid file encodings
@@ -451,7 +464,7 @@ var AllView = class AllView extends BaseAppView {
icon.connect('name-changed', this._itemNameChanged.bind(this));
icon.connect('apps-changed', this._redisplay.bind(this));
}
newApps.push(icon);
appIcons.push(icon);
this.folderIcons.push(icon);
});
@@ -464,14 +477,19 @@ var AllView = class AllView extends BaseAppView {
let favoritesWritable = global.settings.is_writable('favorite-apps');
apps.forEach(appId => {
let app = appSys.lookup_app(appId);
let icon = this._items[appId];
if (!icon) {
let app = appSys.lookup_app(appId);
let icon = new AppIcon(app,
{ isDraggable: favoritesWritable });
newApps.push(icon);
icon = new AppIcon(app, {
isDraggable: favoritesWritable,
});
}
appIcons.push(icon);
});
return newApps;
return appIcons;
}
// Overridden from BaseAppView
@@ -506,7 +524,7 @@ var AllView = class AllView extends BaseAppView {
opacity: 0,
duration: VIEWS_SWITCH_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.opacity = 255
onComplete: () => (this.opacity = 255)
});
if (animationDirection == IconGrid.AnimationDirection.OUT)
@@ -649,7 +667,7 @@ var AllView = class AllView extends BaseAppView {
addFolderPopup(popup) {
this._stack.add_actor(popup.actor);
popup.connect('open-state-changed', (popup, isOpen) => {
this._eventBlocker.reactive = isOpen;
this._eventBlocker.visible = isOpen;
if (this._currentPopup) {
this._currentPopup.actor.disconnect(this._currentPopupDestroyId);
@@ -663,7 +681,7 @@ var AllView = class AllView extends BaseAppView {
this._currentPopupDestroyId = popup.actor.connect('destroy', () => {
this._currentPopup = null;
this._currentPopupDestroyId = 0;
this._eventBlocker.reactive = false;
this._eventBlocker.visible = false;
});
}
this._updateIconOpacities(isOpen);
@@ -731,30 +749,58 @@ var AllView = class AllView extends BaseAppView {
this.folderIcons[i].adaptToSize(availWidth, availHeight);
}
_resetOvershoot() {
if (this._lastOvershootTimeoutId)
GLib.source_remove(this._lastOvershootTimeoutId);
this._lastOvershootTimeoutId = 0;
this._lastOvershootY = -1;
}
_handleDragOvershoot(dragEvent) {
let [, gridY] = this.actor.get_transformed_position();
let [, gridHeight] = this.actor.get_transformed_size();
let gridBottom = gridY + gridHeight;
// Within the grid boundaries, or already animating
if (dragEvent.y > gridY && dragEvent.y < gridBottom ||
this._adjustment.get_transition('value') != null) {
// Already animating
if (this._adjustment.get_transition('value') !== null)
return;
// Within the grid boundaries
if (dragEvent.y > gridY && dragEvent.y < gridBottom) {
// Check whether we moved out the area of the last switch
if (Math.abs(this._lastOvershootY - dragEvent.y) > OVERSHOOT_THRESHOLD)
this._resetOvershoot();
return;
}
// Moving above the grid
// Still in the area of the previous page switch
if (this._lastOvershootY >= 0)
return;
let currentY = this._adjustment.value;
if (dragEvent.y <= gridY && currentY > 0) {
this.goToPage(this._grid.currentPage - 1);
return;
}
// Moving below the grid
let maxY = this._adjustment.upper - this._adjustment.page_size;
if (dragEvent.y >= gridBottom && currentY < maxY) {
if (dragEvent.y <= gridY && currentY > 0)
this.goToPage(this._grid.currentPage - 1);
else if (dragEvent.y >= gridBottom && currentY < maxY)
this.goToPage(this._grid.currentPage + 1);
return;
}
else
return; // don't go beyond first/last page
this._lastOvershootY = dragEvent.y;
if (this._lastOvershootTimeoutId > 0)
GLib.source_remove(this._lastOvershootTimeoutId);
this._lastOvershootTimeoutId =
GLib.timeout_add(GLib.PRIORITY_DEFAULT, OVERSHOOT_TIMEOUT, () => {
this._resetOvershoot();
this._handleDragOvershoot(dragEvent);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._lastOvershootTimeoutId,
'[gnome-shell] this._lastOvershootTimeoutId');
}
_onDragBegin() {
@@ -762,6 +808,8 @@ var AllView = class AllView extends BaseAppView {
dragMotion: this._onDragMotion.bind(this)
};
DND.addDragMonitor(this._dragMonitor);
this._eventBlocker.visible = false;
}
_onDragMotion(dragEvent) {
@@ -784,6 +832,9 @@ var AllView = class AllView extends BaseAppView {
DND.removeDragMonitor(this._dragMonitor);
this._dragMonitor = null;
}
this._eventBlocker.visible = this._currentPopup !== null;
this._resetOvershoot();
}
_canAccept(source) {
@@ -817,19 +868,6 @@ var AllView = class AllView extends BaseAppView {
return true;
}
inhibitEventBlocker() {
this._nEventBlockerInhibits++;
this._eventBlocker.visible = this._nEventBlockerInhibits == 0;
}
uninhibitEventBlocker() {
if (this._nEventBlockerInhibits === 0)
throw new Error('Not inhibited');
this._nEventBlockerInhibits--;
this._eventBlocker.visible = this._nEventBlockerInhibits == 0;
}
createFolder(apps) {
let newFolderId = GLib.uuid_string_random();
@@ -920,8 +958,12 @@ var FrequentView = class FrequentView extends BaseAppView {
for (let i = 0; i < mostUsed.length; i++) {
if (!mostUsed[i].get_app_info().should_show())
continue;
let appIcon = new AppIcon(mostUsed[i],
{ isDraggable: favoritesWritable });
let appIcon = this._items[mostUsed[i].get_id()];
if (!appIcon) {
appIcon = new AppIcon(mostUsed[i], {
isDraggable: favoritesWritable,
});
}
apps.push(appIcon);
}
@@ -1108,8 +1150,9 @@ var AppDisplay = class AppDisplay {
else
this._views[i].control.remove_style_pseudo_class('checked');
let animationDirection = i == activeIndex ? IconGrid.AnimationDirection.IN :
IconGrid.AnimationDirection.OUT;
let animationDirection = i == activeIndex
? IconGrid.AnimationDirection.IN
: IconGrid.AnimationDirection.OUT;
this._views[i].view.animateSwitch(animationDirection);
}
}
@@ -1159,11 +1202,10 @@ var AppSearchProvider = class AppSearchProvider {
if (id.endsWith('.desktop')) {
let app = this._appSys.lookup_app(id);
metas.push({ 'id': app.get_id(),
'name': app.get_name(),
'createIcon'(size) {
return app.create_icon_texture(size);
}
metas.push({
id: app.get_id(),
name: app.get_name(),
createIcon: size => app.create_icon_texture(size),
});
} else {
let name = this._systemActions.getName(id);
@@ -1351,7 +1393,10 @@ var FolderView = class FolderView extends BaseAppView {
if (apps.some(appIcon => appIcon.id == appId))
return;
let icon = new AppIcon(app);
let icon = this._items[appId];
if (!icon)
icon = new AppIcon(app);
apps.push(icon);
};
@@ -1389,15 +1434,15 @@ var FolderView = class FolderView extends BaseAppView {
// Remove the folder if this is the last app icon; otherwise,
// just remove the icon
if (folderApps.length == 0) {
let settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
let folders = settings.get_strv('folder-children');
folders.splice(folders.indexOf(this._id), 1);
settings.set_strv('folder-children', folders);
// Resetting all keys deletes the relocatable schema
let keys = this._folder.settings_schema.list_keys();
for (let key of keys)
this._folder.reset(key);
let settings = new Gio.Settings({ schema_id: 'org.gnome.desktop.app-folders' });
let folders = settings.get_strv('folder-children');
folders.splice(folders.indexOf(this._id), 1);
settings.set_strv('folder-children', folders);
} else {
this._folder.set_strv('apps', folderApps);
}
@@ -1438,6 +1483,13 @@ var FolderIcon = class FolderIcon {
this._itemDragEndId = Main.overview.connect(
'item-drag-end', this._onDragEnd.bind(this));
this._popupTimeoutId = 0;
this.actor.connect('leave-event', this._onLeaveEvent.bind(this));
this.actor.connect('button-press-event', this._onButtonPress.bind(this));
this.actor.connect('touch-event', this._onTouchEvent.bind(this));
this.actor.connect('popup-menu', this._popupRenamePopup.bind(this));
this.actor.connect('clicked', this.open.bind(this));
this.actor.connect('destroy', this.onDestroy.bind(this));
this.actor.connect('notify::mapped', () => {
@@ -1462,9 +1514,12 @@ var FolderIcon = class FolderIcon {
if (this._popup)
this._popup.actor.destroy();
this._removeMenuTimeout();
}
open() {
this._removeMenuTimeout();
this._ensurePopup();
this.view.actor.vscroll.adjustment.value = 0;
this._openSpaceForPopup();
@@ -1479,8 +1534,6 @@ var FolderIcon = class FolderIcon {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
this._parentView.inhibitEventBlocker();
}
_onDragMotion(dragEvent) {
@@ -1496,7 +1549,6 @@ var FolderIcon = class FolderIcon {
_onDragEnd() {
this.actor.remove_style_pseudo_class('drop');
this._parentView.uninhibitEventBlocker();
DND.removeDragMonitor(this._dragMonitor);
}
@@ -1627,6 +1679,74 @@ var FolderIcon = class FolderIcon {
this._popupInvalidated = false;
}
_removeMenuTimeout() {
if (this._popupTimeoutId > 0) {
GLib.source_remove(this._popupTimeoutId);
this._popupTimeoutId = 0;
}
}
_setPopupTimeout() {
this._removeMenuTimeout();
this._popupTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MENU_POPUP_TIMEOUT, () => {
this._popupTimeoutId = 0;
this._popupRenamePopup();
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._popupTimeoutId,
'[gnome-shell] this._popupRenamePopup');
}
_onLeaveEvent(_actor, _event) {
this.actor.fake_release();
this._removeMenuTimeout();
}
_onButtonPress(_actor, event) {
let button = event.get_button();
if (button == 1) {
this._setPopupTimeout();
} else if (button == 3) {
this._popupRenamePopup();
return Clutter.EVENT_STOP;
}
return Clutter.EVENT_PROPAGATE;
}
_onTouchEvent(actor, event) {
if (event.type() == Clutter.EventType.TOUCH_BEGIN)
this._setPopupTimeout();
return Clutter.EVENT_PROPAGATE;
}
_popupRenamePopup() {
this._removeMenuTimeout();
this.actor.fake_release();
if (!this._menu) {
this._menuManager = new PopupMenu.PopupMenuManager(this.actor);
this._menu = new RenameFolderMenu(this, this._folder);
this._menuManager.addMenu(this._menu);
this._menu.connect('open-state-changed', (menu, isPoppedUp) => {
if (!isPoppedUp)
this.actor.sync_hover();
});
let id = Main.overview.connect('hiding', () => {
this._menu.close();
});
this.actor.connect('destroy', () => {
Main.overview.disconnect(id);
});
}
this.actor.set_hover(true);
this._menu.open();
this._menuManager.ignoreRelease();
}
adaptToSize(width, height) {
this._parentAvailableWidth = width;
this._parentAvailableHeight = height;
@@ -1637,6 +1757,106 @@ var FolderIcon = class FolderIcon {
};
Signals.addSignalMethods(FolderIcon.prototype);
var RenameFolderMenuItem = GObject.registerClass(
class RenameFolderMenuItem extends PopupMenu.PopupBaseMenuItem {
_init(folder) {
super._init({
style_class: 'rename-folder-popup-item',
reactive: false,
});
this.setOrnament(PopupMenu.Ornament.HIDDEN);
this._folder = folder;
// Entry
this._entry = new St.Entry({
x_expand: true,
width: 200,
});
this.add_child(this._entry);
this._entry.clutter_text.connect(
'notify::text', this._validate.bind(this));
this._entry.clutter_text.connect(
'activate', this._updateFolderName.bind(this));
// Rename button
this._button = new St.Button({
style_class: 'button',
reactive: true,
button_mask: St.ButtonMask.ONE | St.ButtonMask.TWO,
can_focus: true,
label: _('Rename'),
});
this.add_child(this._button);
this._button.connect('clicked', this._updateFolderName.bind(this));
}
vfunc_map() {
this._entry.text = _getFolderName(this._folder);
this._entry.clutter_text.set_selection(0, -1);
super.vfunc_map();
}
vfunc_key_focus_in() {
super.vfunc_key_focus_in();
this._entry.clutter_text.grab_key_focus();
}
_isValidFolderName() {
let folderName = _getFolderName(this._folder);
let newFolderName = this._entry.text.trim();
return newFolderName.length > 0 && newFolderName != folderName;
}
_validate() {
let isValid = this._isValidFolderName();
this._button.reactive = isValid;
}
_updateFolderName() {
if (!this._isValidFolderName())
return;
let newFolderName = this._entry.text.trim();
this._folder.set_string('name', newFolderName);
this._folder.set_boolean('translate', false);
this.activate(Clutter.get_current_event());
}
});
var RenameFolderMenu = class RenameFolderMenu extends PopupMenu.PopupMenu {
constructor(source, folder) {
super(source.actor, 0.5, St.Side.BOTTOM);
this.actor.add_style_class_name('rename-folder-popup');
// We want to keep the item hovered while the menu is up
this.blockSourceEvents = true;
let menuItem = new RenameFolderMenuItem(folder);
this.addMenuItem(menuItem);
// Focus the text entry on menu pop-up
this.focusActor = menuItem;
// Chain our visibility and lifecycle to that of the source
this._sourceMappedId = source.actor.connect('notify::mapped', () => {
if (!source.actor.mapped)
this.close();
});
source.actor.connect('destroy', () => {
source.actor.disconnect(this._sourceMappedId);
this.destroy();
});
Main.uiGroup.add_actor(this.actor);
}
};
Signals.addSignalMethods(RenameFolderMenu.prototype);
var AppFolderPopup = class AppFolderPopup {
constructor(source, side) {
this._source = source;
@@ -1722,15 +1942,17 @@ var AppFolderPopup = class AppFolderPopup {
direction = St.DirectionType.TAB_FORWARD;
break;
case Clutter.Right:
direction = isLtr ? St.DirectionType.TAB_FORWARD :
St.DirectionType.TAB_BACKWARD;
direction = isLtr
? St.DirectionType.TAB_FORWARD
: St.DirectionType.TAB_BACKWARD;
break;
case Clutter.Up:
direction = St.DirectionType.TAB_BACKWARD;
break;
case Clutter.Left:
direction = isLtr ? St.DirectionType.TAB_BACKWARD :
St.DirectionType.TAB_FORWARD;
direction = isLtr
? St.DirectionType.TAB_BACKWARD
: St.DirectionType.TAB_FORWARD;
break;
default:
return Clutter.EVENT_PROPAGATE;
@@ -1816,17 +2038,10 @@ var AppIcon = class AppIcon {
x_fill: true,
y_fill: true });
this._dot = new St.Widget({ style_class: 'app-well-app-running-dot',
layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END });
this._iconContainer = new St.Widget({ layout_manager: new Clutter.BinLayout(),
x_expand: true, y_expand: true });
this.actor.set_child(this._iconContainer);
this._iconContainer.add_child(this._dot);
this.actor._delegate = this;
@@ -1843,6 +2058,16 @@ var AppIcon = class AppIcon {
this.icon = new IconGrid.BaseIcon(app.get_name(), iconParams);
this._iconContainer.add_child(this.icon);
this._dot = new St.Widget({
style_class: 'app-well-app-running-dot',
layout_manager: new Clutter.BinLayout(),
x_expand: true,
y_expand: true,
x_align: Clutter.ActorAlign.CENTER,
y_align: Clutter.ActorAlign.END,
});
this._iconContainer.add_child(this._dot);
this.actor.label_actor = this.icon.label;
this.actor.connect('leave-event', this._onLeaveEvent.bind(this));
@@ -1873,6 +2098,7 @@ var AppIcon = class AppIcon {
});
}
this._dragMonitor = null;
this._itemDragBeginId = Main.overview.connect(
'item-drag-begin', this._onDragBegin.bind(this));
this._itemDragEndId = Main.overview.connect(
@@ -1897,6 +2123,12 @@ var AppIcon = class AppIcon {
}
if (this._stateChangedId > 0)
this.app.disconnect(this._stateChangedId);
if (this._dragMonitor) {
DND.removeDragMonitor(this._dragMonitor);
this._dragMonitor = null;
}
if (this._draggable) {
if (this._dragging)
Main.overview.endItemDrag(this);
@@ -1912,7 +2144,7 @@ var AppIcon = class AppIcon {
_removeMenuTimeout() {
if (this._menuTimeoutId > 0) {
Mainloop.source_remove(this._menuTimeoutId);
GLib.source_remove(this._menuTimeoutId);
this._menuTimeoutId = 0;
}
}
@@ -1926,7 +2158,7 @@ var AppIcon = class AppIcon {
_setPopupTimeout() {
this._removeMenuTimeout();
this._menuTimeoutId = Mainloop.timeout_add(MENU_POPUP_TIMEOUT, () => {
this._menuTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MENU_POPUP_TIMEOUT, () => {
this._menuTimeoutId = 0;
this.popupMenu();
return GLib.SOURCE_REMOVE;
@@ -2044,6 +2276,10 @@ var AppIcon = class AppIcon {
this.icon.animateZoomOut();
}
animateLaunchAtPos(x, y) {
this.icon.animateZoomOutAtPos(x, y);
}
scaleIn() {
this.actor.scale_x = 0;
this.actor.scale_y = 0;
@@ -2051,13 +2287,16 @@ var AppIcon = class AppIcon {
this.actor.ease({
scale_x: 1,
scale_y: 1,
time: APP_ICON_SCALE_IN_TIME,
duration: APP_ICON_SCALE_IN_TIME,
delay: APP_ICON_SCALE_IN_DELAY,
mode: Clutter.AnimationMode.EASE_OUT_QUINT
});
}
shellWorkspaceLaunch(params) {
let { stack } = new Error();
log(`shellWorkspaceLaunch is deprecated, use app.open_new_window() instead\n${stack}`);
params = Params.parse(params, { workspace: -1,
timestamp: 0 });
@@ -2234,8 +2473,8 @@ var AppIconMenu = class AppIconMenu extends PopupMenu.PopupMenu {
);
windows.forEach(window => {
let title = window.title ? window.title
: this._source.app.get_name();
let title = window.title
? window.title : this._source.app.get_name();
let item = this._appendMenuItem(title);
item.connect('activate', () => {
this.emit('activate-window', window);

View File

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

View File

@@ -161,7 +161,7 @@ var AudioDeviceSelectionDBus = class AudioDeviceSelectionDBus {
let [deviceNames] = params;
let devices = 0;
deviceNames.forEach(n => devices |= AudioDevice[n.toUpperCase()]);
deviceNames.forEach(n => (devices |= AudioDevice[n.toUpperCase()]));
let dialog;
try {

View File

@@ -441,20 +441,21 @@ var Background = class Background {
}
_loadAnimation(file) {
this._cache.getAnimation({ file: file,
settingsSchema: this._settings.schema_id,
onLoaded: animation => {
this._animation = animation;
this._cache.getAnimation({
file: file,
settingsSchema: this._settings.schema_id,
onLoaded: animation => {
this._animation = animation;
if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded();
return;
}
if (!this._animation || this._cancellable.is_cancelled()) {
this._setLoaded();
return;
}
this._updateAnimation();
this._watchFile(file);
}
});
this._updateAnimation();
this._watchFile(file);
}
});
}
_loadImage(file) {
@@ -748,13 +749,14 @@ var BackgroundManager = class BackgroundManager {
_createBackgroundActor() {
let background = this._backgroundSource.getBackground(this._monitorIndex);
let backgroundActor = new Meta.BackgroundActor({ meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,
vignette_sharpness: 0.5,
brightness: 0.5,
});
let backgroundActor = new Meta.BackgroundActor({
meta_display: global.display,
monitor: this._monitorIndex,
background: background.background,
vignette: this._vignette,
vignette_sharpness: 0.5,
brightness: 0.5,
});
this._container.add_child(backgroundActor);

View File

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

View File

@@ -172,8 +172,8 @@ var BoxPointer = GObject.registerClass({
let borderWidth = themeNode.get_length('-arrow-border-width');
minSize += borderWidth * 2;
natSize += borderWidth * 2;
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM))
|| (isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
if ((!isWidth && (this._arrowSide == St.Side.TOP || this._arrowSide == St.Side.BOTTOM)) ||
(isWidth && (this._arrowSide == St.Side.LEFT || this._arrowSide == St.Side.RIGHT))) {
let rise = themeNode.get_length('-arrow-rise');
minSize += rise;
natSize += rise;

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Calendar, CalendarMessageList */
const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const { Clutter, Gio, GLib, GObject, Shell, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -581,8 +581,9 @@ var Calendar = class Calendar {
if (row == 2)
styleClass = `calendar-day-top ${styleClass}`;
let leftMost = rtl ? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
let leftMost = rtl
? iter.getDay() == (this._weekStart + 6) % 7
: iter.getDay() == this._weekStart;
if (leftMost)
styleClass = `calendar-day-left ${styleClass}`;
@@ -680,23 +681,24 @@ var EventMessage = class EventMessage extends MessageList.Message {
*/
title = C_("event list time", "All Day");
} else {
let date = this._event.date >= periodBegin ? this._event.date
: this._event.end;
let date = this._event.date >= periodBegin
? this._event.date
: this._event.end;
title = Util.formatTime(date, { timeOnly: true });
}
let rtl = Clutter.get_default_text_direction() == Clutter.TextDirection.RTL;
if (this._event.date < periodBegin && !this._event.allDay) {
if (rtl)
title = title + ELLIPSIS_CHAR;
title = `${title}${ELLIPSIS_CHAR}`;
else
title = ELLIPSIS_CHAR + title;
title = `${ELLIPSIS_CHAR}${title}`;
}
if (this._event.end > periodEnd && !this._event.allDay) {
if (rtl)
title = ELLIPSIS_CHAR + title;
title = `${ELLIPSIS_CHAR}${title}`;
else
title = title + ELLIPSIS_CHAR;
title = `${title}${ELLIPSIS_CHAR}`;
}
return title;
}
@@ -1071,10 +1073,14 @@ var CalendarMessageList = class CalendarMessageList {
this._clearButton.set_x_align(Clutter.ActorAlign.END);
this._clearButton.connect('clicked', () => {
let sections = [...this._sections.keys()];
sections.forEach((s) => s.clear());
sections.forEach(s => s.clear());
});
box.add_actor(this._clearButton);
this._placeholder.actor.bind_property('visible',
this._clearButton, 'visible',
GObject.BindingFlags.INVERT_BOOLEAN);
this._sectionList = new St.BoxLayout({ style_class: 'message-list-sections',
vertical: true,
y_expand: true,
@@ -1145,7 +1151,6 @@ var CalendarMessageList = class CalendarMessageList {
let empty = sections.every(s => s.empty || !s.actor.visible);
this._placeholder.actor.visible = empty;
this._clearButton.visible = !empty;
let canClear = sections.some(s => s.canClear && s.actor.visible);
this._clearButton.reactive = canClear;

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported CloseDialog */
const { Clutter, Gio, GLib, GObject, Meta, Shell } = imports.gi;
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
@@ -46,6 +46,18 @@ var CloseDialog = GObject.registerClass({
return new Dialog.MessageDialogContent({ icon, title, subtitle });
}
_updateScale() {
// Since this is a child of MetaWindowActor (which, for Wayland clients,
// applies the geometry scale factor to its children itself, see
// meta_window_actor_set_geometry_scale()), make sure we don't apply
// the factor twice in the end.
if (this._window.get_client_type() !== Meta.WindowClientType.WAYLAND)
return;
let { scaleFactor } = St.ThemeContext.get_for_stage(global.stage);
this._dialog.set_scale(1 / scaleFactor, 1 / scaleFactor);
}
_initDialog() {
if (this._dialog)
return;
@@ -64,6 +76,11 @@ var CloseDialog = GObject.registerClass({
key: Clutter.Escape });
global.focus_manager.add_group(this._dialog);
let themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.connect('notify::scale-factor', this._updateScale.bind(this));
this._updateScale();
}
_addWindowEffect() {
@@ -145,10 +162,10 @@ var CloseDialog = GObject.registerClass({
this._addWindowEffect();
this._initDialog();
this._dialog.scale_y = 0;
this._dialog.set_pivot_point(0.5, 0.5);
this._dialog._dialog.scale_y = 0;
this._dialog._dialog.set_pivot_point(0.5, 0.5);
this._dialog.ease({
this._dialog._dialog.ease({
scale_y: 1,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,
@@ -175,7 +192,8 @@ var CloseDialog = GObject.registerClass({
this._dialog = null;
this._removeWindowEffect();
dialog.ease({
dialog.makeInactive();
dialog._dialog.ease({
scale_y: 0,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,

View File

@@ -2,7 +2,6 @@
/* exported Component */
const { Gio, GLib } = imports.gi;
const Mainloop = imports.mainloop;
const Params = imports.misc.params;
const GnomeSession = imports.misc.gnomeSession;
@@ -39,7 +38,7 @@ var AutomountManager = class {
this._driveDisconnectedId = this._volumeMonitor.connect('drive-disconnected', this._onDriveDisconnected.bind(this));
this._driveEjectButtonId = this._volumeMonitor.connect('drive-eject-button', this._onDriveEjectButton.bind(this));
this._mountAllId = Mainloop.idle_add(this._startupMountAll.bind(this));
this._mountAllId = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._startupMountAll.bind(this));
GLib.Source.set_name_by_id(this._mountAllId, '[gnome-shell] this._startupMountAll');
}
@@ -51,7 +50,7 @@ var AutomountManager = class {
this._volumeMonitor.disconnect(this._driveEjectButtonId);
if (this._mountAllId > 0) {
Mainloop.source_remove(this._mountAllId);
GLib.source_remove(this._mountAllId);
this._mountAllId = 0;
}
}
@@ -157,7 +156,7 @@ var AutomountManager = class {
!volume.should_automount() ||
!volume.can_mount()) {
// allow the autorun to run anyway; this can happen if the
// mount gets added programmatically later, even if
// mount gets added programmatically later, even if
// should_automount() or can_mount() are false, like for
// blank optical media.
this._allowAutorun(volume);
@@ -220,17 +219,17 @@ var AutomountManager = class {
_onVolumeRemoved(monitor, volume) {
if (volume._allowAutorunExpireId && volume._allowAutorunExpireId > 0) {
Mainloop.source_remove(volume._allowAutorunExpireId);
GLib.source_remove(volume._allowAutorunExpireId);
delete volume._allowAutorunExpireId;
}
this._volumeQueue =
this._volumeQueue =
this._volumeQueue.filter(element => (element != volume));
}
_reaskPassword(volume) {
let prevOperation = this._activeOperations.get(volume);
let existingDialog = prevOperation ? prevOperation.borrowDialog() : null;
let operation =
let operation =
new ShellMountOperation.ShellMountOperation(volume,
{ existingDialog: existingDialog });
this._mountVolume(volume, operation);
@@ -249,7 +248,7 @@ var AutomountManager = class {
}
_allowAutorunExpire(volume) {
let id = Mainloop.timeout_add_seconds(AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
let id = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, AUTORUN_EXPIRE_TIMEOUT_SECS, () => {
volume.allowAutorun = false;
delete volume._allowAutorunExpireId;
return GLib.SOURCE_REMOVE;

View File

@@ -63,7 +63,7 @@ function startAppForMount(app, mount) {
files.push(root);
try {
retval = app.launch(files,
retval = app.launch(files,
global.create_app_launch_context(0, -1));
} catch (e) {
log(`Unable to launch the application ${app.get_name()}: ${e}`);
@@ -72,8 +72,6 @@ function startAppForMount(app, mount) {
return retval;
}
/******************************************/
const HotplugSnifferIface = loadInterfaceXML('org.gnome.Shell.HotplugSniffer');
const HotplugSnifferProxy = Gio.DBusProxy.makeProxyWrapper(HotplugSnifferIface);
function HotplugSniffer() {
@@ -117,9 +115,9 @@ var ContentTypeDiscoverer = class {
let hotplugSniffer = new HotplugSniffer();
hotplugSniffer.SniffURIRemote(root.get_uri(),
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
});
([contentTypes]) => {
this._emitCallback(mount, contentTypes);
});
}
}
@@ -215,11 +213,11 @@ var AutorunDispatcher = class {
}
_addSource(mount, apps) {
// if we already have a source showing for this
// if we already have a source showing for this
// mount, return
if (this._getSourceForMount(mount))
return;
// add a new source
this._sources.push(new AutorunSource(this._manager, mount, apps));
}
@@ -264,7 +262,7 @@ var AutorunDispatcher = class {
removeMount(mount) {
let source = this._getSourceForMount(mount);
// if we aren't tracking this mount, don't do anything
if (!source)
return;
@@ -325,10 +323,10 @@ var AutorunNotification = class extends MessageTray.Notification {
style_class: 'hotplug-notification-item-icon' });
box.add(icon);
let label = new St.Bin({ y_align: St.Align.MIDDLE,
child: new St.Label
({ text: _("Open with %s").format(app.get_name()) })
});
let label = new St.Bin({
y_align: St.Align.MIDDLE,
child: new St.Label({ text: _("Open with %s").format(app.get_name()) }),
});
box.add(label);
let button = new St.Button({ child: box,

View File

@@ -74,7 +74,9 @@ class KeyringDialog extends ModalDialog.ModalDialog {
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this._passwordEntry.clutter_text.connect('activate', this._onPasswordActivate.bind(this));
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true,
});
if (rtl) {
layout.attach(this._workSpinner.actor, 0, row, 1, 1);
@@ -232,8 +234,9 @@ var KeyringPrompter = class {
constructor() {
this._prompter = new Gcr.SystemPrompter();
this._prompter.connect('new-prompt', () => {
let dialog = this._enabled ? new KeyringDialog()
: new KeyringDummyDialog();
let dialog = this._enabled
? new KeyringDialog()
: new KeyringDummyDialog();
this._currentPrompt = dialog.prompt;
return this._currentPrompt;
});

View File

@@ -4,13 +4,15 @@
const { Clutter, Gio, GLib, GObject, NM, Pango, Shell, St } = imports.gi;
const Signals = imports.signals;
const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
Gio._promisify(Shell.NetworkAgent.prototype,
'search_vpn_plugin', 'search_vpn_plugin_finish');
const VPN_UI_GROUP = 'VPN Plugin UI';
var NetworkSecretDialog = GObject.registerClass(
@@ -112,16 +114,17 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
expand: true });
}
this._okButton = { label: _("Connect"),
action: this._onOk.bind(this),
default: true
};
this._okButton = {
label: _("Connect"),
action: this._onOk.bind(this),
default: true,
};
this.setButtons([{ label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
},
this._okButton]);
this.setButtons([{
label: _("Cancel"),
action: this.cancel.bind(this),
key: Clutter.KEY_Escape,
}, this._okButton]);
this._updateOkButton();
}
@@ -163,9 +166,9 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (value.length == 64) {
// must be composed of hexadecimal digits only
for (let i = 0; i < 64; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
if (!((value[i] >= 'a' && value[i] <= 'f') ||
(value[i] >= 'A' && value[i] <= 'F') ||
(value[i] >= '0' && value[i] <= '9')))
return false;
}
return true;
@@ -179,15 +182,15 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
if (secret.wep_key_type == NM.WepKeyType.KEY) {
if (value.length == 10 || value.length == 26) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'f')
|| (value[i] >= 'A' && value[i] <= 'F')
|| (value[i] >= '0' && value[i] <= '9')))
if (!((value[i] >= 'a' && value[i] <= 'f') ||
(value[i] >= 'A' && value[i] <= 'F') ||
(value[i] >= '0' && value[i] <= '9')))
return false;
}
} else if (value.length == 5 || value.length == 13) {
for (let i = 0; i < value.length; i++) {
if (!((value[i] >= 'a' && value[i] <= 'z')
|| (value[i] >= 'A' && value[i] <= 'Z')))
if (!((value[i] >= 'a' && value[i] <= 'z') ||
(value[i] >= 'A' && value[i] <= 'Z')))
return false;
}
} else {
@@ -212,6 +215,7 @@ class NetworkSecretDialog extends ModalDialog.ModalDialog {
// First the easy ones
case 'wpa-none':
case 'wpa-psk':
case 'sae':
secrets.push({ label: _("Password: "), key: 'psk',
value: wirelessSecuritySetting.psk || '',
validate: this._validateWpaPsk, password: true });
@@ -551,11 +555,12 @@ var VPNRequestHandler = class {
let shouldAsk = keyfile.get_boolean(groups[i], 'ShouldAsk');
if (shouldAsk) {
contentOverride.secrets.push({ label: keyfile.get_string(groups[i], 'Label'),
key: groups[i],
value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret')
});
contentOverride.secrets.push({
label: keyfile.get_string(groups[i], 'Label'),
key: groups[i],
value: value,
password: keyfile.get_boolean(groups[i], 'IsSecret'),
});
} else {
if (!value.length) // Ignore empty secrets
continue;
@@ -609,23 +614,16 @@ Signals.addSignalMethods(VPNRequestHandler.prototype);
var NetworkAgent = class {
constructor() {
this._native = new Shell.NetworkAgent({ identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false
});
this._native = new Shell.NetworkAgent({
identifier: 'org.gnome.Shell.NetworkAgent',
capabilities: NM.SecretAgentCapabilities.VPN_HINTS,
auto_register: false,
});
this._dialogs = { };
this._vpnRequests = { };
this._notifications = { };
this._pluginDir = Gio.file_new_for_path(Config.VPNDIR);
try {
let monitor = this._pluginDir.monitor(Gio.FileMonitorFlags.NONE, null);
monitor.connect('changed', () => this._vpnCacheBuilt = false);
} catch (e) {
log(`Failed to create monitor for VPN plugin dir: ${e.message}`);
}
this._native.connect('new-request', this._newRequest.bind(this));
this._native.connect('cancel-request', this._cancelRequest.bind(this));
@@ -765,13 +763,11 @@ var NetworkAgent = class {
}
}
_vpnRequest(requestId, connection, hints, flags) {
async _vpnRequest(requestId, connection, hints, flags) {
let vpnSetting = connection.get_setting_vpn();
let serviceType = vpnSetting.service_type;
this._buildVPNServiceCache();
let binary = this._vpnBinaries[serviceType];
let binary = await this._findAuthBinary(serviceType);
if (!binary) {
log('Invalid VPN service type (cannot find authentication binary)');
@@ -787,36 +783,30 @@ var NetworkAgent = class {
this._vpnRequests[requestId] = vpnRequest;
}
_buildVPNServiceCache() {
if (this._vpnCacheBuilt)
return;
async _findAuthBinary(serviceType) {
let plugin;
this._vpnCacheBuilt = true;
this._vpnBinaries = { };
try {
plugin = await this._native.search_vpn_plugin(serviceType);
} catch (e) {
logError(e);
return null;
}
NM.VpnPluginInfo.list_load().forEach(plugin => {
let service = plugin.get_service();
let fileName = plugin.get_auth_dialog();
let supportsHints = plugin.supports_hints();
let externalUIMode = false;
const fileName = plugin.get_auth_dialog();
if (!GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
log('VPN plugin at %s is not executable'.format(fileName));
return null;
}
let prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
if (prop) {
prop = prop.trim().toLowerCase();
externalUIMode = ['true', 'yes', 'on', '1'].includes(prop);
}
const prop = plugin.lookup_property('GNOME', 'supports-external-ui-mode');
const trimmedProp = prop ? prop.trim().toLowerCase() : '';
if (GLib.file_test(fileName, GLib.FileTest.IS_EXECUTABLE)) {
let binary = { fileName, externalUIMode, supportsHints };
this._vpnBinaries[service] = binary;
plugin.get_aliases().forEach(alias => {
this._vpnBinaries[alias] = binary;
});
} else {
log('VPN plugin at %s is not executable'.format(fileName));
}
});
return {
fileName,
supportsHints: plugin.supports_hints(),
externalUIMode: ['true', 'yes', 'on', '1'].includes(trimmedProp),
};
}
};
var Component = NetworkAgent;

View File

@@ -11,6 +11,11 @@ const ModalDialog = imports.ui.modalDialog;
const ShellEntry = imports.ui.shellEntry;
const UserWidget = imports.ui.userWidget;
const DialogMode = {
AUTH: 0,
CONFIRM: 1,
};
var DIALOG_ICON_SIZE = 48;
var WORK_SPINNER_ICON_SIZE = 16;
@@ -51,47 +56,32 @@ var AuthenticationDialog = GObject.registerClass({
userName = userNames[0];
this._user = AccountsService.UserManager.get_default().get_user(userName);
let userRealName = this._user.get_real_name();
this._userLoadedId = this._user.connect('notify::is_loaded',
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
this._onUserChanged.bind(this));
// Special case 'root'
let userIsRoot = false;
if (userName == 'root') {
userIsRoot = true;
userRealName = _("Administrator");
}
let userBox = new St.BoxLayout({
style_class: 'polkit-dialog-user-layout',
vertical: false,
});
content.messageBox.add(userBox);
if (userIsRoot) {
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-root-label',
text: userRealName }));
content.messageBox.add(userLabel, { x_fill: false,
x_align: St.Align.START });
} else {
let userBox = new St.BoxLayout({ style_class: 'polkit-dialog-user-layout',
vertical: false });
content.messageBox.add(userBox);
this._userAvatar = new UserWidget.Avatar(this._user,
{ iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon' });
this._userAvatar.actor.hide();
userBox.add(this._userAvatar.actor,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.START });
let userLabel = new St.Label(({ style_class: 'polkit-dialog-user-label',
text: userRealName }));
userBox.add(userLabel,
{ x_fill: true,
y_fill: false,
x_align: St.Align.END,
y_align: St.Align.MIDDLE });
}
this._userAvatar = new UserWidget.Avatar(this._user, {
iconSize: DIALOG_ICON_SIZE,
styleClass: 'polkit-dialog-user-icon',
});
this._userAvatar.actor.hide();
userBox.add_child(this._userAvatar.actor);
this._onUserChanged();
this._userLabel = new St.Label({
style_class: userName === 'root'
? 'polkit-dialog-user-root-label'
: 'polkit-dialog-user-label',
x_expand: true,
y_align: Clutter.ActorAlign.CENTER,
});
if (userName === 'root')
this._userLabel.text = _('Administrator');
userBox.add_child(this._userLabel);
this._passwordBox = new St.BoxLayout({ vertical: false, style_class: 'prompt-dialog-password-box' });
content.messageBox.add(this._passwordBox);
@@ -105,10 +95,11 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.add(this._passwordEntry,
{ expand: true });
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true,
});
this._passwordBox.add(this._workSpinner.actor);
this.setInitialKeyFocus(this._passwordEntry);
this._passwordBox.hide();
this._errorMessageLabel = new St.Label({ style_class: 'prompt-dialog-error-label' });
@@ -144,8 +135,16 @@ var AuthenticationDialog = GObject.registerClass({
this._doneEmitted = false;
this._mode = -1;
this._identityToAuth = Polkit.UnixUser.new_for_name(userName);
this._cookie = cookie;
this._userLoadedId = this._user.connect('notify::is-loaded',
this._onUserChanged.bind(this));
this._userChangedId = this._user.connect('changed',
this._onUserChanged.bind(this));
this._onUserChanged();
}
_setWorking(working) {
@@ -155,8 +154,9 @@ var AuthenticationDialog = GObject.registerClass({
this._workSpinner.stop();
}
performAuthentication() {
_initiateSession() {
this._destroySession();
this._session = new PolkitAgent.Session({ identity: this._identityToAuth,
cookie: this._cookie });
this._sessionCompletedId = this._session.connect('completed', this._onSessionCompleted.bind(this));
@@ -216,7 +216,10 @@ var AuthenticationDialog = GObject.registerClass({
}
_onAuthenticateButtonPressed() {
this._onEntryActivate();
if (this._mode === DialogMode.CONFIRM)
this._initiateSession();
else
this._onEntryActivate();
}
_onSessionCompleted(session, gainedAuthorization) {
@@ -247,7 +250,7 @@ var AuthenticationDialog = GObject.registerClass({
}
/* Try and authenticate again */
this.performAuthentication();
this._initiateSession();
}
}
@@ -265,9 +268,10 @@ var AuthenticationDialog = GObject.registerClass({
this._passwordBox.show();
this._passwordEntry.set_text('');
this._passwordEntry.grab_key_focus();
this._updateSensitivity(true);
this._ensureOpen();
this._passwordEntry.grab_key_focus();
}
_onSessionShowError(session, text) {
@@ -303,10 +307,40 @@ var AuthenticationDialog = GObject.registerClass({
}
_onUserChanged() {
if (this._user.is_loaded && this._userAvatar) {
if (!this._user.is_loaded)
return;
let userName = this._user.get_user_name();
let realName = this._user.get_real_name();
if (userName !== 'root') {
this._userLabel.set_text(realName);
this._userAvatar.update();
this._userAvatar.actor.show();
}
if (this._user.get_password_mode() === AccountsService.UserPasswordMode.NONE) {
if (this._mode === DialogMode.CONFIRM)
return;
this._mode = DialogMode.CONFIRM;
this._destroySession();
this._okButton.reactive = true;
/* We normally open the dialog when we get a "request" signal, but
* since in this case initiating a session would perform the
* authentication, only open the dialog and initiate the session
* when the user confirmed. */
this._ensureOpen();
} else {
if (this._mode === DialogMode.AUTH)
return;
this._mode = DialogMode.AUTH;
this._initiateSession();
}
}
cancel() {
@@ -369,19 +403,7 @@ var AuthenticationAgent = class {
}
this._currentDialog = new AuthenticationDialog(actionId, message, cookie, userNames);
// We actually don't want to open the dialog until we know for
// sure that we're going to interact with the user. For
// example, if the password for the identity to auth is blank
// (which it will be on a live CD) then there will be no
// conversation at all... of course, we don't *know* that
// until we actually try it.
//
// See https://bugzilla.gnome.org/show_bug.cgi?id=643062 for more
// discussion.
this._currentDialog.connect('done', this._onDialogDone.bind(this));
this._currentDialog.performAuthentication();
}
_onCancel(_nativeAgent) {

View File

@@ -3,7 +3,6 @@
const { Clutter, Gio, GLib, GObject, St } = imports.gi;
const Lang = imports.lang;
const Mainloop = imports.mainloop;
var Tpl = null;
var Tp = null;
@@ -546,8 +545,8 @@ var ChatSource = class extends MessageTray.Source {
// Wait a bit before notifying for the received message, a handler
// could ack it in the meantime.
if (this._notifyTimeoutId != 0)
Mainloop.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = Mainloop.timeout_add(500,
GLib.source_remove(this._notifyTimeoutId);
this._notifyTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500,
this._notifyTimeout.bind(this));
GLib.Source.set_name_by_id(this._notifyTimeoutId, '[gnome-shell] this._notifyTimeout');
}
@@ -584,7 +583,7 @@ var ChatSource = class extends MessageTray.Source {
let msg = Tp.ClientMessage.new_text(type, text);
this._channel.send_message_async(msg, 0, (src, result) => {
this._channel.send_message_finish(result);
this._channel.send_message_finish(result);
});
}
@@ -641,7 +640,7 @@ var ChatNotification = class extends MessageTray.Notification {
destroy(reason) {
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
super.destroy(reason);
}
@@ -654,7 +653,7 @@ var ChatNotification = class extends MessageTray.Notification {
* sender: the name of the sender,
* timestamp: the time the message was sent
* direction: a #NotificationDirection
*
*
* @noTimestamp: Whether to add a timestamp. If %true, no timestamp
* will be added, regardless of the difference since the
* last timestamp
@@ -674,8 +673,8 @@ var ChatNotification = class extends MessageTray.Notification {
{ datetime: GLib.DateTime.new_from_unix_local (message.timestamp),
bannerMarkup: true });
let group = (message.direction == NotificationDirection.RECEIVED ?
'received' : 'sent');
let group = (message.direction == NotificationDirection.RECEIVED
? 'received' : 'sent');
this._append({ body: messageBody,
group: group,
@@ -697,8 +696,8 @@ var ChatNotification = class extends MessageTray.Notification {
// SCROLLBACK_RECENT_LENGTH previous messages. Otherwise
// we'll keep SCROLLBACK_IDLE_LENGTH messages.
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME) ?
SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let maxLength = (lastMessageTime < currentTime - SCROLLBACK_RECENT_TIME)
? SCROLLBACK_IDLE_LENGTH : SCROLLBACK_RECENT_LENGTH;
let filteredHistory = this.messages.filter(item => item.realMessage);
if (filteredHistory.length > maxLength) {
@@ -729,7 +728,7 @@ var ChatNotification = class extends MessageTray.Notification {
// Reset the old message timeout
if (this._timestampTimeoutId)
Mainloop.source_remove(this._timestampTimeoutId);
GLib.source_remove(this._timestampTimeoutId);
this._timestampTimeoutId = 0;
let message = { realMessage: props.group != 'meta',
@@ -747,7 +746,8 @@ var ChatNotification = class extends MessageTray.Notification {
} else {
// Schedule a new timestamp in SCROLLBACK_IMMEDIATE_TIME
// from the timestamp of the message.
this._timestampTimeoutId = Mainloop.timeout_add_seconds(
this._timestampTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
SCROLLBACK_IMMEDIATE_TIME - (currentTime - timestamp),
this.appendTimestamp.bind(this));
GLib.Source.set_name_by_id(this._timestampTimeoutId, '[gnome-shell] this.appendTimestamp');
@@ -952,14 +952,15 @@ var ChatNotificationBanner = class extends MessageTray.NotificationBanner {
// Remove composing timeout.
if (this._composingTimeoutId > 0) {
Mainloop.source_remove(this._composingTimeoutId);
GLib.source_remove(this._composingTimeoutId);
this._composingTimeoutId = 0;
}
if (text != '') {
this.notification.source.setChatState(Tp.ChannelChatState.COMPOSING);
this._composingTimeoutId = Mainloop.timeout_add_seconds(
this._composingTimeoutId = GLib.timeout_add_seconds(
GLib.PRIORITY_DEFAULT,
COMPOSING_STOP_TIMEOUT,
this._composingStopTimeout.bind(this));
GLib.Source.set_name_by_id(this._composingTimeoutId, '[gnome-shell] this._composingStopTimeout');

View File

@@ -2,7 +2,6 @@
/* exported Dash */
const { Clutter, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AppDisplay = imports.ui.appDisplay;
@@ -500,7 +499,7 @@ var Dash = class Dash {
// that the notify::hover handler does everything we need to.
if (opened) {
if (this._showLabelTimeoutId > 0) {
Mainloop.source_remove(this._showLabelTimeoutId);
GLib.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
}
@@ -514,7 +513,7 @@ var Dash = class Dash {
if (shouldShow) {
if (this._showLabelTimeoutId == 0) {
let timeout = this._labelShowing ? 0 : DASH_ITEM_HOVER_TIMEOUT;
this._showLabelTimeoutId = Mainloop.timeout_add(timeout,
this._showLabelTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout,
() => {
this._labelShowing = true;
item.showLabel();
@@ -523,17 +522,17 @@ var Dash = class Dash {
});
GLib.Source.set_name_by_id(this._showLabelTimeoutId, '[gnome-shell] item.showLabel');
if (this._resetHoverTimeoutId > 0) {
Mainloop.source_remove(this._resetHoverTimeoutId);
GLib.source_remove(this._resetHoverTimeoutId);
this._resetHoverTimeoutId = 0;
}
}
} else {
if (this._showLabelTimeoutId > 0)
Mainloop.source_remove(this._showLabelTimeoutId);
GLib.source_remove(this._showLabelTimeoutId);
this._showLabelTimeoutId = 0;
item.hideLabel();
if (this._labelShowing) {
this._resetHoverTimeoutId = Mainloop.timeout_add(DASH_ITEM_HOVER_TIMEOUT,
this._resetHoverTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DASH_ITEM_HOVER_TIMEOUT,
() => {
this._labelShowing = false;
this._resetHoverTimeoutId = 0;
@@ -624,7 +623,7 @@ var Dash = class Dash {
icon.icon.ease({
width: targetWidth,
height: targetHeight,
time: DASH_ANIMATION_TIME,
duration: DASH_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
}
@@ -704,8 +703,8 @@ var Dash = class Dash {
}
// App moved
let nextApp = newApps.length > newIndex + 1 ? newApps[newIndex + 1]
: null;
let nextApp = newApps.length > newIndex + 1
? newApps[newIndex + 1] : null;
let insertHere = nextApp && nextApp == oldApp;
let alreadyRemoved = removedActors.reduce((result, actor) => {
let removedApp = actor.child._delegate.app;

View File

@@ -30,11 +30,13 @@ var TodayButton = class TodayButton {
// Having the ability to go to the current date if the user is already
// on the current date can be confusing. So don't make the button reactive
// until the selected date changes.
this.actor = new St.Button({ style_class: 'datemenu-today-button',
x_expand: true, x_align: St.Align.START,
can_focus: true,
reactive: false
});
this.actor = new St.Button({
style_class: 'datemenu-today-button',
x_align: St.Align.START,
x_expand: true,
can_focus: true,
reactive: false,
});
this.actor.connect('clicked', () => {
this._calendar.setDate(new Date(), false);
});
@@ -146,8 +148,9 @@ var WorldClocksSection = class WorldClocksSection {
});
let layout = this._grid.layout_manager;
let title = (this._locations.length == 0) ? _("Add world clocks…")
: _("World Clocks");
let title = (this._locations.length == 0)
? _("Add world clocks")
: _("World Clocks");
let header = new St.Label({ style_class: 'world-clocks-header',
x_align: Clutter.ActorAlign.START,
text: title });
@@ -410,7 +413,7 @@ var MessagesIndicator = class MessagesIndicator {
_updateCount() {
let count = 0;
this._sources.forEach(source => count += source.unseenCount);
this._sources.forEach(source => (count += source.unseenCount));
count -= Main.messageTray.queueCount;
this.actor.visible = (count > 0);

View File

@@ -51,10 +51,16 @@ class Dialog extends St.Widget {
y_align: St.Align.START });
}
_onDestroy() {
makeInactive() {
if (this._eventId != 0)
this._parentActor.disconnect(this._eventId);
this._eventId = 0;
this.buttonLayout.get_children().forEach(c => c.set_reactive(false));
}
_onDestroy() {
this.makeInactive();
}
_modalEventHandler(actor, event) {

View File

@@ -573,11 +573,15 @@ var _Draggable = class _Draggable {
while (target) {
if (target._delegate && target._delegate.acceptDrop) {
let [r_, targX, targY] = target.transform_stage_point(dropX, dropY);
if (target._delegate.acceptDrop(this.actor._delegate,
this._dragActor,
targX,
targY,
event.get_time())) {
let accepted = false;
try {
accepted = target._delegate.acceptDrop(this.actor._delegate,
this._dragActor, targX, targY, event.get_time());
} catch (e) {
// On error, skip this target
logError(e, "Skipping drag target");
}
if (accepted) {
// If it accepted the drop without taking the actor,
// handle it ourselves.
if (this._dragActor && this._dragActor.get_parent() == Main.uiGroup) {

View File

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

View File

@@ -10,7 +10,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, Shell, St } = imports.gi;
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have
@@ -58,17 +58,16 @@ function _patchLayoutClass(layoutClass, styleProps) {
};
}
function _makeEaseCallback(params) {
function _makeEaseCallback(params, cleanup) {
let onComplete = params.onComplete;
delete params.onComplete;
let onStopped = params.onStopped;
delete params.onStopped;
if (!onComplete && !onStopped)
return null;
return isFinished => {
cleanup();
if (onStopped)
onStopped(isFinished);
if (onComplete && isFinished)
@@ -110,7 +109,8 @@ function _easeActor(actor, params) {
actor.set_easing_mode(params.mode);
delete params.mode;
let callback = _makeEaseCallback(params);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transitions
let animatedProps = Object.keys(params).map(p => p.replace('_', '-', 'g'));
@@ -119,14 +119,18 @@ function _easeActor(actor, params) {
actor.set(params);
actor.restore_easing_state();
if (callback) {
let transition = actor.get_transition(animatedProps[0]);
let transition = animatedProps.map(p => actor.get_transition(p))
.find(t => t !== null);
if (transition)
transition.connect('stopped', (t, finished) => callback(finished));
else
callback(true);
}
if (transition && transition.delay)
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
else
Meta.disable_unredirect_for_display(global.display);
if (transition)
transition.connect('stopped', (t, finished) => callback(finished));
else
callback(true);
}
function _easeActorProperty(actor, propName, target, params) {
@@ -139,7 +143,13 @@ function _easeActorProperty(actor, propName, target, params) {
params.duration = adjustAnimationTime(params.duration);
let duration = Math.floor(params.duration || 0);
let callback = _makeEaseCallback(params);
// Copy Clutter's behavior for implicit animations, see
// should_skip_implicit_transition()
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
// cancel overwritten transition
actor.remove_transition(propName);
@@ -148,8 +158,8 @@ function _easeActorProperty(actor, propName, target, params) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
if (callback)
callback(true);
Meta.disable_unredirect_for_display(global.display);
callback(true);
return;
}
@@ -164,8 +174,12 @@ function _easeActorProperty(actor, propName, target, params) {
transition.set_to(target);
if (callback)
transition.connect('stopped', (t, finished) => callback(finished));
if (transition.delay)
transition.connect('started', () => Meta.disable_unredirect_for_display(global.display));
else
Meta.disable_unredirect_for_display(global.display);
transition.connect('stopped', (t, finished) => callback(finished));
}
function _loggingFunc(...args) {

View File

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

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
const { Gio, St } = imports.gi;
const { GLib, Gio, St } = imports.gi;
const Signals = imports.signals;
const ExtensionUtils = imports.misc.extensionUtils;
@@ -17,7 +17,7 @@ const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validatio
var ExtensionManager = class {
constructor() {
this._initted = false;
this._initialized = false;
this._enabled = false;
this._extensions = new Map();
@@ -28,6 +28,23 @@ var ExtensionManager = class {
}
init() {
// The following file should exist for a period of time when extensions
// are enabled after start. If it exists, then the systemd unit will
// disable extensions should gnome-shell crash.
// Should the file already exist from a previous login, then this is OK.
let disableFilename = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gnome-shell-disable-extensions']);
let disableFile = Gio.File.new_for_path(disableFilename);
try {
disableFile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, null);
} catch (e) {
log(`Failed to create file ${disableFilename}: ${e.message}`);
}
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
FileUtils.deleteGFile(disableFile);
return GLib.SOURCE_REMOVE;
});
this._sessionUpdated();
}
@@ -98,6 +115,9 @@ var ExtensionManager = class {
}
_callExtensionEnable(uuid) {
if (!Main.sessionMode.allowExtensions)
return;
let extension = this.lookup(uuid);
if (!extension)
return;
@@ -108,8 +128,6 @@ var ExtensionManager = class {
if (extension.state != ExtensionState.DISABLED)
return;
this._extensionOrder.push(uuid);
let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
for (let i = 0; i < stylesheetNames.length; i++) {
@@ -121,7 +139,7 @@ var ExtensionManager = class {
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue; // not an error
log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
this.logExtensionError(uuid, e);
return;
}
}
@@ -129,15 +147,14 @@ var ExtensionManager = class {
try {
extension.stateObj.enable();
extension.state = ExtensionState.ENABLED;
this._extensionOrder.push(uuid);
this.emit('extension-state-changed', extension);
return;
} catch (e) {
if (extension.stylesheet) {
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
this.logExtensionError(uuid, e);
return;
}
}
@@ -194,7 +211,7 @@ var ExtensionManager = class {
extension.errors = [];
extension.errors.push(message);
log('Extension "%s" had error: %s'.format(uuid, message));
logError(error, `Extension ${uuid}`);
this.emit('extension-state-changed', extension);
}
@@ -286,7 +303,7 @@ var ExtensionManager = class {
reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: type } = oldExtension;
let { uuid, dir, type } = oldExtension;
// Then unload the old extension.
this.unloadExtension(oldExtension);
@@ -304,12 +321,14 @@ var ExtensionManager = class {
}
_callExtensionInit(uuid) {
if (!Main.sessionMode.allowExtensions)
return false;
let extension = this.lookup(uuid);
let dir = extension.dir;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
throw new Error("Extension was not properly created. Call createExtensionObject first");
let dir = extension.dir;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
@@ -388,9 +407,6 @@ var ExtensionManager = class {
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
if (!this._enabled)
return;
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions.filter(
@@ -401,9 +417,9 @@ var ExtensionManager = class {
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
this._enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).forEach(uuid => {
this._extensionOrder.filter(
uuid => !newEnabledExtensions.includes(uuid)
).reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
@@ -418,22 +434,19 @@ var ExtensionManager = class {
}
_onVersionValidationChanged() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
this._enabledExtensions = [];
// Disabling extensions modifies the order array, so use a copy
let extensionOrder = this._extensionOrder.slice();
// The loop modifies the extensions map, so iterate over a copy
let extensions = [...this._extensions.values()];
for (let extension of extensions)
this.reloadExtension(extension);
this._enabledExtensions = this._getEnabledExtensions();
// Disable enabled extensions in the reverse order first to avoid
// the "rebasing" done in _callExtensionDisable...
extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
if (Main.sessionMode.allowExtensions) {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
// ...and then reload and enable extensions in the correct order again.
[...this._extensions.values()].sort((a, b) => {
return extensionOrder.indexOf(a.uuid) - extensionOrder.indexOf(b.uuid);
}).forEach(extension => this.reloadExtension(extension));
}
_loadExtensions() {
@@ -482,9 +495,9 @@ var ExtensionManager = class {
if (this._enabled)
return;
if (!this._initted) {
if (!this._initialized) {
this._loadExtensions();
this._initted = true;
this._initialized = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
@@ -497,7 +510,7 @@ var ExtensionManager = class {
if (!this._enabled)
return;
if (this._initted) {
if (this._initialized) {
this._extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
@@ -512,8 +525,8 @@ var ExtensionManager = class {
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
if (this._initted)
this._enabledExtensions = this._getEnabledExtensions();
// Take care of added or removed sessionMode extensions
this._onEnabledExtensionsChanged();
this._enableAllExtensions();
} else {
this._disableAllExtensions();

View File

@@ -126,6 +126,9 @@ Signals.addSignalMethods(CandidateArea.prototype);
var CandidatePopup = class CandidatePopup {
constructor() {
this._dummyCursor = new St.Widget({ opacity: 0 });
Main.layoutManager.uiGroup.add_actor(this._dummyCursor);
this._boxPointer = new BoxPointer.BoxPointer(St.Side.TOP);
this._boxPointer.visible = false;
this._boxPointer.style_class = 'candidate-popup-boxpointer';
@@ -272,9 +275,11 @@ var CandidatePopup = class CandidatePopup {
}
_setDummyCursorGeometry(x, y, w, h) {
Main.layoutManager.setDummyCursorGeometry(x, y, w, h);
this._dummyCursor.set_position(Math.round(x), Math.round(y));
this._dummyCursor.set_size(Math.round(w), Math.round(h));
if (this._boxPointer.visible)
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._boxPointer.setPosition(this._dummyCursor, 0);
}
_updateVisibility() {
@@ -284,7 +289,7 @@ var CandidatePopup = class CandidatePopup {
this._candidateArea.actor.visible));
if (isVisible) {
this._boxPointer.setPosition(Main.layoutManager.dummyCursor, 0);
this._boxPointer.setPosition(this._dummyCursor, 0);
this._boxPointer.open(BoxPointer.PopupAnimation.NONE);
this._boxPointer.raise_top();
} else {

View File

@@ -142,6 +142,10 @@ class BaseIcon extends St.Bin {
zoomOutActor(this.child);
}
animateZoomOutAtPos(x, y) {
zoomOutActorAtPos(this.child, x, y);
}
update() {
this._createIconTexture(this.iconSize);
}
@@ -152,10 +156,15 @@ function clamp(value, min, max) {
}
function zoomOutActor(actor) {
let [x, y] = actor.get_transformed_position();
zoomOutActorAtPos(actor, x, y);
}
function zoomOutActorAtPos(actor, x, y) {
let actorClone = new Clutter.Clone({ source: actor,
reactive: false });
let [width, height] = actor.get_transformed_size();
let [x, y] = actor.get_transformed_position();
actorClone.set_size(width, height);
actorClone.set_position(x, y);
actorClone.opacity = 255;
@@ -247,10 +256,23 @@ var IconGrid = GObject.registerClass({
_childAdded(grid, child) {
child._iconGridKeyFocusInId = child.connect('key-focus-in', this._keyFocusIn.bind(this));
child._paintVisible = child.opacity > 0;
child._opacityChangedId = child.connect('notify::opacity', () => {
let paintVisible = child._paintVisible;
child._paintVisible = child.opacity > 0;
if (paintVisible !== child._paintVisible)
this.queue_relayout();
});
}
_childRemoved(grid, child) {
child.disconnect(child._iconGridKeyFocusInId);
delete child._iconGridKeyFocusInId;
child.disconnect(child._opacityChangedId);
delete child._opacityChangedId;
delete child._paintVisible;
}
vfunc_get_preferred_width(_forHeight) {
@@ -260,9 +282,9 @@ var IconGrid = GObject.registerClass({
return [0, 0];
let nChildren = this.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
let nColumns = this._colLimit
? Math.min(this._colLimit, nChildren)
: nChildren;
let totalSpacing = Math.max(0, nColumns - 1) * this._getSpacing();
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
@@ -414,7 +436,7 @@ var IconGrid = GObject.registerClass({
* set of items to be animated.
*/
_getChildrenToAnimate() {
return this._getVisibleChildren();
return this._getVisibleChildren().filter(child => child.opacity > 0);
}
_resetAnimationActors() {
@@ -774,8 +796,9 @@ var IconGrid = GObject.registerClass({
let neededWidth = this.usedWidthForNColumns(this._minColumns) - availWidth;
let neededHeight = this.usedHeightForNRows(this._minRows) - availHeight;
let neededSpacePerItem = (neededWidth > neededHeight) ? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
let neededSpacePerItem = (neededWidth > neededHeight)
? Math.ceil(neededWidth / this._minColumns)
: Math.ceil(neededHeight / this._minRows);
this._fixedHItemSize = Math.max(this._hItemSize - neededSpacePerItem, MIN_ICON_SIZE);
this._fixedVItemSize = Math.max(this._vItemSize - neededSpacePerItem, MIN_ICON_SIZE);
@@ -871,7 +894,7 @@ var PaginatedIconGrid = GObject.registerClass({
// Overridden from IconGrid
_getChildrenToAnimate() {
let children = this._getVisibleChildren();
let children = super._getChildrenToAnimate();
let firstIndex = this._childrenPerPage * this.currentPage;
let lastIndex = firstIndex + this._childrenPerPage;
@@ -950,8 +973,7 @@ var PaginatedIconGrid = GObject.registerClass({
let childrenPerRow = this._childrenPerPage / this._rowsPerPage;
let sourceRow = Math.floor((index - pageOffset) / childrenPerRow);
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1
: sourceRow;
let nRowsAbove = (side == St.Side.TOP) ? sourceRow + 1 : sourceRow;
let nRowsBelow = this._rowsPerPage - nRowsAbove;
let nRowsUp, nRowsDown;

View File

@@ -76,8 +76,9 @@ var InhibitShortcutsDialog = GObject.registerClass({
let name = this._app ? this._app.get_name() : this._window.title;
/* Translators: %s is an application name like "Settings" */
let title = name ? _("%s wants to inhibit shortcuts").format(name)
: _("Application wants to inhibit shortcuts");
let title = name
? _("%s wants to inhibit shortcuts").format(name)
: _("Application wants to inhibit shortcuts");
let icon = new Gio.ThemedIcon({ name: 'dialog-warning-symbolic' });
let contentParams = { icon, title };

View File

@@ -27,24 +27,24 @@ class KbdA11yDialog extends GObject.Object {
if (whatChanged & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) {
key = KEY_SLOW_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) ? true : false;
title = enabled ?
_("Slow Keys Turned On") :
_("Slow Keys Turned Off");
enabled = (newFlags & Clutter.KeyboardA11yFlags.SLOW_KEYS_ENABLED) > 0;
title = enabled
? _("Slow Keys Turned On")
: _("Slow Keys Turned Off");
body = _("You just held down the Shift key for 8 seconds. This is the shortcut " +
"for the Slow Keys feature, which affects the way your keyboard works.");
} else if (whatChanged & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) {
key = KEY_STICKY_KEYS_ENABLED;
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) ? true : false;
title = enabled ?
_("Sticky Keys Turned On") :
_("Sticky Keys Turned Off");
body = enabled ?
_("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.") :
_("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
enabled = (newFlags & Clutter.KeyboardA11yFlags.STICKY_KEYS_ENABLED) > 0;
title = enabled
? _("Sticky Keys Turned On")
: _("Sticky Keys Turned Off");
body = enabled
? _("You just pressed the Shift key 5 times in a row. This is the shortcut " +
"for the Sticky Keys feature, which affects the way your keyboard works.")
: _("You just pressed two keys at once, or pressed the Shift key 5 times in a row. " +
"This turns off the Sticky Keys feature, which affects the way your keyboard works.");
} else {
return;
}

View File

@@ -104,9 +104,10 @@ class KeyContainer extends St.Widget {
this._currentRow++;
this._currentCol = 0;
let row = new Object();
row.keys = [];
row.width = 0;
let row = {
keys: [],
width: 0,
};
this._rows.push(row);
}
@@ -193,12 +194,12 @@ var LanguageSelectionPopup = class extends PopupMenu.PopupMenu {
item = this.addAction(is.displayName, () => {
inputSourceManager.activateInputSource(is, true);
});
item.actor.can_focus = false;
item.can_focus = false;
}
this.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
item = this.addSettingsAction(_("Region & Language Settings"), 'gnome-region-panel.desktop');
item.actor.can_focus = false;
item.can_focus = false;
this._capturedEventId = 0;
@@ -465,10 +466,17 @@ Signals.addSignalMethods(Key.prototype);
var KeyboardModel = class {
constructor(groupName) {
try {
this._model = this._loadModel(groupName);
} catch (e) {
this._model = this._loadModel('us');
let names = [groupName];
if (groupName.includes('+'))
names.push(groupName.replace(/\+.*/, ''));
names.push('us');
for (let i = 0; i < names.length; i++) {
try {
this._model = this._loadModel(names[i]);
break;
} catch (e) {
}
}
}
@@ -574,7 +582,7 @@ var EmojiPager = GObject.registerClass({
'delta': GObject.ParamSpec.int(
'delta', 'delta', 'delta',
GObject.ParamFlags.READWRITE,
0, GLib.MAXINT32, 0)
GLib.MININT32, GLib.MAXINT32, 0)
},
Signals: {
'emoji': { param_types: [GObject.TYPE_STRING] },
@@ -886,7 +894,7 @@ var EmojiSelection = class EmojiSelection {
this._emojiPager.connect('emoji', (pager, str) => {
this.emit('emoji-selected', str);
});
this.actor.add(this._emojiPager.actor, { expand: true });
this.actor.add(this._emojiPager, { expand: true });
this._pageIndicator = new PageIndicators.PageIndicators(false);
this.actor.add(this._pageIndicator, { expand: true, x_fill: false, y_fill: false });
@@ -1080,7 +1088,7 @@ var Keyboard = class Keyboard {
this.hide();
});
Meta.get_backend().connect('last-device-changed',
Meta.get_backend().connect('last-device-changed',
(backend, deviceId) => {
let manager = Clutter.DeviceManager.get_default();
let device = manager.get_device(deviceId);

View File

@@ -189,6 +189,7 @@ var LayoutManager = GObject.registerClass({
'startup-complete': {},
'startup-prepared': {},
'monitors-changed': {},
'system-modal-opened': {},
'keyboard-visible-changed': { param_types: [GObject.TYPE_BOOLEAN] } },
}, class LayoutManager extends GObject.Object {
_init() {
@@ -238,11 +239,12 @@ var LayoutManager = GObject.registerClass({
reactive: true });
this.addChrome(this.overviewGroup);
this.screenShieldGroup = new St.Widget({ name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.screenShieldGroup = new St.Widget({
name: 'screenShieldGroup',
visible: false,
clip_to_allocation: true,
layout_manager: new Clutter.BinLayout(),
});
this.addChrome(this.screenShieldGroup);
this.panelBox = new St.BoxLayout({ name: 'panelBox',
@@ -770,8 +772,7 @@ var LayoutManager = GObject.registerClass({
this.keyboardBox.ease({
anchor_y: 0,
opacity: 0,
duration: immediate ? 0
: KEYBOARD_ANIMATION_TIME,
duration: immediate ? 0 : KEYBOARD_ANIMATION_TIME,
mode: Clutter.AnimationMode.EASE_IN_QUAD,
onComplete: () => {
this._hideKeyboardComplete();
@@ -855,12 +856,13 @@ var LayoutManager = GObject.registerClass({
index = this._findActor(ancestor);
}
let ancestorData = ancestor ? this._trackedActors[index]
: defaultParams;
let ancestorData = ancestor
? this._trackedActors[index]
: defaultParams;
// We can't use Params.parse here because we want to drop
// the extra values like ancestorData.actor
for (let prop in defaultParams) {
if (!params.hasOwnProperty(prop))
if (!Object.prototype.hasOwnProperty.call(params, prop))
params[prop] = ancestorData[prop];
}
@@ -1014,11 +1016,6 @@ var LayoutManager = GObject.registerClass({
if (Main.modalCount > 0)
return GLib.SOURCE_REMOVE;
// Bug workaround - get_transformed_position()/get_transformed_size() don't work after
// a change in stage size until the first pick or paint.
// https://bugzilla.gnome.org/show_bug.cgi?id=761565
global.stage.get_actor_at_pos(Clutter.PickMode.ALL, 0, 0);
let rects = [], struts = [], i;
let isPopupMenuVisible = global.top_window_group.get_children().some(isPopupMetaWindow);
let wantsInputRegion = !isPopupMenuVisible;
@@ -1074,16 +1071,17 @@ var LayoutManager = GObject.registerClass({
side = Meta.Side.RIGHT;
else
continue;
} else if (x1 <= monitor.x)
} else if (x1 <= monitor.x) {
side = Meta.Side.LEFT;
else if (y1 <= monitor.y)
} else if (y1 <= monitor.y) {
side = Meta.Side.TOP;
else if (x2 >= monitor.x + monitor.width)
} else if (x2 >= monitor.x + monitor.width) {
side = Meta.Side.RIGHT;
else if (y2 >= monitor.y + monitor.height)
} else if (y2 >= monitor.y + monitor.height) {
side = Meta.Side.BOTTOM;
else
} else {
continue;
}
let strutRect = new Meta.Rectangle({ x: x1, y: y1, width: x2 - x1, height: y2 - y1 });
let strut = new Meta.Strut({ rect: strutRect, side: side });
@@ -1224,6 +1222,8 @@ var HotCorner = class HotCorner {
if (this.actor)
this.actor.destroy();
this._ripples.destroy();
}
_toggleOverview() {

View File

@@ -108,12 +108,13 @@ var RadialShaderEffect = GObject.registerClass({
*/
var Lightbox = class Lightbox {
constructor(container, params) {
params = Params.parse(params, { inhibitEvents: false,
width: null,
height: null,
fadeFactor: DEFAULT_FADE_FACTOR,
radialEffect: false,
});
params = Params.parse(params, {
inhibitEvents: false,
width: null,
height: null,
fadeFactor: DEFAULT_FADE_FACTOR,
radialEffect: false,
});
this._container = container;
this._children = container.get_children();
@@ -172,66 +173,52 @@ var Lightbox = class Lightbox {
}
show(fadeInTime) {
fadeInTime = fadeInTime || 0;
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeInTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => {
this.shown = true;
this.emit('shown');
};
this.actor.show();
if (this._radialEffect) {
this.actor.ease_property(
'@effects.radial.brightness', VIGNETTE_BRIGHTNESS, {
duration: fadeInTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
'@effects.radial.brightness', VIGNETTE_BRIGHTNESS, easeProps);
this.actor.ease_property(
'@effects.radial.sharpness', VIGNETTE_SHARPNESS, {
duration: fadeInTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
'@effects.radial.sharpness', VIGNETTE_SHARPNESS,
Object.assign({ onComplete }, easeProps));
} else {
this.actor.ease({
this.actor.ease(Object.assign(easeProps, {
opacity: 255 * this._fadeFactor,
duration: fadeInTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
}));
}
this.actor.show();
}
hide(fadeOutTime) {
fadeOutTime = fadeOutTime || 0;
this.shown = false;
this.actor.remove_all_transitions();
let easeProps = {
duration: fadeOutTime || 0,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
};
let onComplete = () => this.actor.hide();
if (this._radialEffect) {
this.actor.ease_property(
'@effects.radial.brightness', 1.0, {
duration: fadeOutTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
'@effects.radial.brightness', 1.0, easeProps);
this.actor.ease_property(
'@effects.radial.sharpness', 0.0, {
duration: fadeOutTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
'@effects.radial.sharpness', 0.0, Object.assign({ onComplete }, easeProps));
} else {
this.actor.ease({
opacity: 0,
duration: fadeOutTime,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete
});
this.actor.ease(Object.assign(easeProps, { opacity: 0, onComplete }));
}
}

View File

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

View File

@@ -3,7 +3,6 @@
const { Clutter, Cogl, Gio, GLib,
GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const System = imports.system;
@@ -20,7 +19,6 @@ const CHEVRON = '>>> ';
/* Imports...feel free to add here as needed */
var commandHeader = 'const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi; ' +
'const Main = imports.ui.main; ' +
'const Mainloop = imports.mainloop; ' +
/* Utility functions...we should probably be able to use these
* in the shell core code too. */
'const stage = global.stage; ' +
@@ -240,7 +238,7 @@ var Notebook = class Notebook {
Signals.addSignalMethods(Notebook.prototype);
function objectToString(o) {
if (typeof(o) == typeof(objectToString)) {
if (typeof o == typeof objectToString) {
// special case this since the default is way, way too verbose
return '<js function>';
} else {
@@ -306,6 +304,9 @@ var WindowList = class WindowList {
}
_updateWindowList() {
if (!this._lookingGlass.isOpen)
return;
this.actor.destroy_all_children();
let windows = global.get_window_actors();
let tracker = Shell.WindowTracker.get_default();
@@ -337,6 +338,10 @@ var WindowList = class WindowList {
}
}
}
update() {
this._updateWindowList();
}
};
Signals.addSignalMethods(WindowList.prototype);
@@ -369,7 +374,7 @@ var ObjInspector = class ObjInspector {
let hbox = new St.BoxLayout({ style_class: 'lg-obj-inspector-title' });
this._container.add_actor(hbox);
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof(obj),
let label = new St.Label({ text: 'Inspecting: %s: %s'.format(typeof obj,
objectToString(obj)) });
label.single_line_mode = true;
hbox.add(label, { expand: true, y_fill: false });
@@ -387,7 +392,7 @@ var ObjInspector = class ObjInspector {
button.add_actor(new St.Icon({ icon_name: 'window-close-symbolic' }));
button.connect('clicked', this.close.bind(this));
hbox.add(button);
if (typeof(obj) == typeof({})) {
if (typeof obj == typeof {}) {
let properties = [];
for (let propName in obj) {
properties.push(propName);
@@ -423,7 +428,7 @@ var ObjInspector = class ObjInspector {
scale_x: 1,
scale_y: 1,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
time: 200
duration: 200
});
} else {
this.actor.set_scale(1, 1);
@@ -821,7 +826,7 @@ var LookingGlass = class LookingGlass {
gcIcon.connect('button-press-event', () => {
gcIcon.icon_name = 'user-trash';
System.gc();
this._timeoutId = Mainloop.timeout_add(500, () => {
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 500, () => {
gcIcon.icon_name = 'user-trash-full';
this._timeoutId = 0;
return GLib.SOURCE_REMOVE;
@@ -876,7 +881,7 @@ var LookingGlass = class LookingGlass {
return true;
});
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entry.clutter_text });
this._autoComplete = new AutoComplete(this._entry);
@@ -1010,7 +1015,11 @@ var LookingGlass = class LookingGlass {
}
getResult(idx) {
return this._results[idx - this._offset].o;
try {
return this._results[idx - this._offset].o;
} catch (e) {
throw new Error(`Unknown result at index ${idx}`);
}
}
toggle() {
@@ -1097,6 +1106,8 @@ var LookingGlass = class LookingGlass {
duration,
mode: Clutter.AnimationMode.EASE_OUT_QUAD
});
this._windowList.update();
}
close() {
@@ -1122,5 +1133,9 @@ var LookingGlass = class LookingGlass {
onComplete: () => this.actor.hide()
});
}
get isOpen() {
return this._open;
}
};
Signals.addSignalMethods(LookingGlass.prototype);

View File

@@ -2,7 +2,6 @@
const { Atspi, Clutter, GDesktopEnums,
Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -128,6 +127,8 @@ var Magnifier = class Magnifier {
* Show the system mouse pointer.
*/
showSystemCursor() {
if (this._cursorTracker.set_keep_focus_while_hidden)
this._cursorTracker.set_keep_focus_while_hidden(false);
this._cursorTracker.set_pointer_visible(true);
}
@@ -136,6 +137,8 @@ var Magnifier = class Magnifier {
* Hide the system mouse pointer.
*/
hideSystemCursor() {
if (this._cursorTracker.set_keep_focus_while_hidden)
this._cursorTracker.set_keep_focus_while_hidden(true);
this._cursorTracker.set_pointer_visible(false);
}
@@ -170,7 +173,7 @@ var Magnifier = class Magnifier {
// Make sure system mouse pointer is shown when all zoom regions are
// invisible.
if (!activate)
this._cursorTracker.set_pointer_visible(true);
this.showSystemCursor();
// Notify interested parties of this change
this.emit('active-changed', activate);
@@ -265,7 +268,7 @@ var Magnifier = class Magnifier {
zoomRegion.setViewPort(viewPort);
// We ignore the redundant width/height on the ROI
let fixedROI = new Object(roi);
let fixedROI = Object.create(roi);
fixedROI.width = viewPort.width / xMagFactor;
fixedROI.height = viewPort.height / yMagFactor;
zoomRegion.setROI(fixedROI);
@@ -452,15 +455,11 @@ var Magnifier = class Magnifier {
* @clip: Flag to indicate whether to clip the crosshairs.
*/
setCrosshairsClip(clip) {
if (clip) {
if (this._crossHairs)
this._crossHairs.setClip(CROSSHAIRS_CLIP_SIZE);
} else {
// Setting no clipping on crosshairs means a zero sized clip
// rectangle.
if (this._crossHairs)
this._crossHairs.setClip([0, 0]);
}
if (!this._crossHairs)
return;
// Setting no clipping on crosshairs means a zero sized clip rectangle.
this._crossHairs.setClip(clip ? CROSSHAIRS_CLIP_SIZE : [0, 0]);
}
/**
@@ -1144,7 +1143,7 @@ var ZoomRegion = class ZoomRegion {
_clearScrollContentsTimer() {
if (this._scrollContentsTimerId != 0) {
Mainloop.source_remove(this._scrollContentsTimerId);
GLib.source_remove(this._scrollContentsTimerId);
this._scrollContentsTimerId = 0;
}
}
@@ -1156,7 +1155,7 @@ var ZoomRegion = class ZoomRegion {
}
this._clearScrollContentsTimer();
this._scrollContentsTimerId = Mainloop.timeout_add(POINTER_REST_TIME, () => {
this._scrollContentsTimerId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, POINTER_REST_TIME, () => {
this._scrollContentsToDelayed(x, y);
return GLib.SOURCE_REMOVE;
});

View File

@@ -9,7 +9,6 @@
initializeDeferredWork, getThemeStylesheet, setThemeStylesheet */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const AccessDialog = imports.ui.accessDialog;
const AudioDeviceSelection = imports.ui.audioDeviceSelection;
@@ -230,7 +229,11 @@ function _initializeUI() {
EndSessionDialog.init();
// We're ready for the session manager to move to the next phase
Meta.register_with_session();
GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
Shell.util_sd_notify();
Meta.register_with_session();
return GLib.SOURCE_REMOVE;
});
_startDate = new Date();
@@ -620,7 +623,7 @@ function _runDeferredWork(workId) {
_deferredWorkQueue.splice(index, 1);
_deferredWorkData[workId].callback();
if (_deferredWorkQueue.length == 0 && _deferredTimeoutId > 0) {
Mainloop.source_remove(_deferredTimeoutId);
GLib.source_remove(_deferredTimeoutId);
_deferredTimeoutId = 0;
}
}
@@ -706,9 +709,8 @@ function queueDeferredWork(workId) {
_deferredWorkQueue.push(workId);
if (data.actor.mapped) {
_queueBeforeRedraw(workId);
return;
} else if (_deferredTimeoutId == 0) {
_deferredTimeoutId = Mainloop.timeout_add_seconds(DEFERRED_TIMEOUT_SECONDS, () => {
_deferredTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, DEFERRED_TIMEOUT_SECONDS, () => {
_runAllDeferredWork();
_deferredTimeoutId = 0;
return GLib.SOURCE_REMOVE;

View File

@@ -333,7 +333,10 @@ var Message = class Message {
let closeIcon = new St.Icon({ icon_name: 'window-close-symbolic',
icon_size: 16 });
this._closeButton = new St.Button({ child: closeIcon, opacity: 0 });
this._closeButton = new St.Button({
style_class: 'message-close-button',
child: closeIcon, opacity: 0,
});
titleBox.add_actor(this._closeButton);
this._bodyStack = new St.Widget({ x_expand: true });

View File

@@ -4,7 +4,6 @@
SystemNotificationSource, MessageTray */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Calendar = imports.ui.calendar;
@@ -137,13 +136,14 @@ var FocusGrabber = class FocusGrabber {
// A notification without a policy object will inherit the default one.
var NotificationPolicy = class NotificationPolicy {
constructor(params) {
params = Params.parse(params, { enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false
});
params = Params.parse(params, {
enable: true,
enableSound: true,
showBanners: true,
forceExpanded: false,
showInLockScreen: true,
detailsInLockScreen: false,
});
Object.getOwnPropertyNames(params).forEach(key => {
let desc = Object.getOwnPropertyDescriptor(params, key);
Object.defineProperty(this, `_${key}`, desc);
@@ -153,6 +153,7 @@ var NotificationPolicy = class NotificationPolicy {
// Do nothing for the default policy. These methods are only useful for the
// GSettings policy.
store() { }
destroy() { }
get enable() {
@@ -334,7 +335,7 @@ class NotificationApplicationPolicy extends NotificationPolicy {
// event sound is played when the notification is shown (if the policy for
// @source allows playing sounds).
//
// [1] https://developer.gnome.org/notification-spec/#markup
// [1] https://developer.gnome.org/notification-spec/#markup
var Notification = class Notification {
constructor(source, title, banner, params) {
this.source = source;
@@ -734,8 +735,9 @@ var Source = class Source {
}
get narrowestPrivacyScope() {
return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM) ? PrivacyScope.SYSTEM
: PrivacyScope.USER;
return this.notifications.every(n => n.privacyScope == PrivacyScope.SYSTEM)
? PrivacyScope.SYSTEM
: PrivacyScope.USER;
}
setTitle(newTitle) {
@@ -1004,7 +1006,6 @@ var MessageTray = class MessageTray {
_addSource(source) {
let obj = {
source: source,
notifyId: 0,
destroyId: 0,
};
@@ -1091,7 +1092,7 @@ var MessageTray = class MessageTray {
_resetNotificationLeftTimeout() {
this._useLongerNotificationLeftTimeout = false;
if (this._notificationLeftTimeoutId) {
Mainloop.source_remove(this._notificationLeftTimeoutId);
GLib.source_remove(this._notificationLeftTimeoutId);
this._notificationLeftTimeoutId = 0;
this._notificationLeftMouseX = -1;
this._notificationLeftMouseY = -1;
@@ -1137,7 +1138,7 @@ var MessageTray = class MessageTray {
// We wait for a longer period if the notification popped up where the mouse pointer was already positioned.
// That gives the user more time to mouse away from the notification and mouse back in in order to expand it.
let timeout = this._useLongerNotificationLeftTimeout ? LONGER_HIDE_TIMEOUT : HIDE_TIMEOUT;
this._notificationLeftTimeoutId = Mainloop.timeout_add(timeout, this._onNotificationLeftTimeout.bind(this));
this._notificationLeftTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout, this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
}
}
@@ -1166,8 +1167,10 @@ var MessageTray = class MessageTray {
x < this._notificationLeftMouseX + MOUSE_LEFT_ACTOR_THRESHOLD &&
x > this._notificationLeftMouseX - MOUSE_LEFT_ACTOR_THRESHOLD) {
this._notificationLeftMouseX = -1;
this._notificationLeftTimeoutId = Mainloop.timeout_add(LONGER_HIDE_TIMEOUT,
this._onNotificationLeftTimeout.bind(this));
this._notificationLeftTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
LONGER_HIDE_TIMEOUT,
this._onNotificationLeftTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationLeftTimeoutId, '[gnome-shell] this._onNotificationLeftTimeout');
} else {
this._notificationLeftTimeoutId = 0;
@@ -1345,13 +1348,13 @@ var MessageTray = class MessageTray {
_updateNotificationTimeout(timeout) {
if (this._notificationTimeoutId) {
Mainloop.source_remove(this._notificationTimeoutId);
GLib.source_remove(this._notificationTimeoutId);
this._notificationTimeoutId = 0;
}
if (timeout > 0) {
this._notificationTimeoutId =
Mainloop.timeout_add(timeout,
this._notificationTimeout.bind(this));
GLib.timeout_add(GLib.PRIORITY_DEFAULT, timeout,
this._notificationTimeout.bind(this));
GLib.Source.set_name_by_id(this._notificationTimeoutId, '[gnome-shell] this._notificationTimeout');
}
}

View File

@@ -216,6 +216,8 @@ var ModalDialog = GObject.registerClass({
if (!Main.pushModal(this, params))
return false;
Main.layoutManager.emit('system-modal-opened');
this._hasModal = true;
if (this._savedKeyFocus) {
this._savedKeyFocus.grab_key_focus();
@@ -253,7 +255,7 @@ var ModalDialog = GObject.registerClass({
opacity: 0,
duration: FADE_OUT_DIALOG_TIME,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
onComplete: () => this.state = State.FADED_OUT
onComplete: () => (this.state = State.FADED_OUT)
});
}
});

View File

@@ -71,8 +71,9 @@ var MediaMessage = class MediaMessage extends MessageList.Message {
}
let isPlaying = this._player.status == 'Playing';
let iconName = isPlaying ? 'media-playback-pause-symbolic'
: 'media-playback-start-symbolic';
let iconName = isPlaying
? 'media-playback-pause-symbolic'
: 'media-playback-start-symbolic';
this._playPauseButton.child.icon_name = iconName;
this._updateNavButton(this._prevButton, this._player.canGoPrevious);

View File

@@ -2,7 +2,6 @@
/* exported NotificationDaemon */
const { GdkPixbuf, Gio, GLib, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Config = imports.misc.config;
const Main = imports.ui.main;
@@ -171,7 +170,7 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
// Ignore replacesId since we already sent back a
// NotificationClosed for that id.
id = this._nextNotificationId++;
let idleId = Mainloop.idle_add(() => {
let idleId = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
this._emitNotificationClosed(id, NotificationClosedReason.DISMISSED);
return GLib.SOURCE_REMOVE;
});
@@ -347,8 +346,9 @@ var FdoNotificationDaemon = class FdoNotificationDaemon {
notification.setTransient(!!hints['transient']);
let privacyScope = (hints['x-gnome-privacy-scope'] || 'user');
notification.setPrivacyScope(privacyScope == 'system' ? MessageTray.PrivacyScope.SYSTEM
: MessageTray.PrivacyScope.USER);
notification.setPrivacyScope(privacyScope == 'system'
? MessageTray.PrivacyScope.SYSTEM
: MessageTray.PrivacyScope.USER);
let sourceGIcon = source.useNotificationIcon ? gicon : null;
source.processNotification(notification, sourceGIcon);
@@ -541,22 +541,23 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
super(source);
this._serialized = GLib.Variant.new('a{sv}', notification);
let { "title": title,
"body": body,
"icon": gicon,
"urgent": urgent,
"priority": priority,
"buttons": buttons,
let { title,
body,
icon: gicon,
urgent,
priority,
buttons,
"default-action": defaultAction,
"default-action-target": defaultActionTarget,
"timestamp": time } = notification;
timestamp: time } = notification;
if (priority) {
let urgency = PRIORITY_URGENCY_MAP[priority.unpack()];
this.setUrgency(urgency != undefined ? urgency : MessageTray.Urgency.NORMAL);
} else if (urgent) {
this.setUrgency(urgent.unpack() ? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
this.setUrgency(urgent.unpack()
? MessageTray.Urgency.CRITICAL
: MessageTray.Urgency.NORMAL);
} else {
this.setUrgency(MessageTray.Urgency.NORMAL);
}
@@ -589,8 +590,8 @@ class GtkNotificationDaemonNotification extends MessageTray.Notification {
}
_onButtonClicked(button) {
let { 'action': action, 'target': actionTarget } = button;
this._activateAction(action.unpack(), actionTarget);
let { action, target } = button;
this._activateAction(action.unpack(), target);
}
activate() {
@@ -617,7 +618,7 @@ function getPlatformData() {
function InvalidAppError() {}
var GtkNotificationDaemonAppSource =
var GtkNotificationDaemonAppSource =
class GtkNotificationDaemonAppSource extends MessageTray.Source {
constructor(appId) {
let objectPath = objectPathFromAppId(appId);
@@ -750,29 +751,33 @@ var GtkNotificationDaemon = class GtkNotificationDaemon {
_loadNotifications() {
this._isLoading = true;
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
return;
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
try {
let value = global.get_persistent_state('a(sa(sv))', 'notifications');
if (value) {
let sources = value.deep_unpack();
sources.forEach(([appId, notifications]) => {
if (notifications.length == 0)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
let source;
try {
source = this._ensureAppSource(appId);
} catch (e) {
if (e instanceof InvalidAppError)
return;
throw e;
}
notifications.forEach(([notificationId, notification]) => {
source.addNotification(notificationId, notification.deep_unpack(), false);
});
});
});
}
} catch (e) {
logError(e, 'Failed to load saved notifications');
} finally {
this._isLoading = false;
}
this._isLoading = false;
}
_saveNotifications() {

View File

@@ -2,7 +2,6 @@
/* exported OsdWindowManager */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const BarLevel = imports.ui.barLevel;
const Layout = imports.ui.layout;
@@ -143,9 +142,9 @@ var OsdWindow = class {
}
if (this._hideTimeoutId)
Mainloop.source_remove(this._hideTimeoutId);
this._hideTimeoutId = Mainloop.timeout_add(HIDE_TIMEOUT,
this._hide.bind(this));
GLib.source_remove(this._hideTimeoutId);
this._hideTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT, HIDE_TIMEOUT, this._hide.bind(this));
GLib.Source.set_name_by_id(this._hideTimeoutId, '[gnome-shell] this._hide');
}
@@ -153,7 +152,7 @@ var OsdWindow = class {
if (!this._hideTimeoutId)
return;
Mainloop.source_remove(this._hideTimeoutId);
GLib.source_remove(this._hideTimeoutId);
this._hide();
}

View File

@@ -2,7 +2,6 @@
/* exported Overview */
const { Clutter, GLib, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -43,9 +42,10 @@ var ShellInfo = class {
}
setMessage(text, options) {
options = Params.parse(options, { undoCallback: null,
forFeedback: false
});
options = Params.parse(options, {
undoCallback: null,
forFeedback: false,
});
let undoCallback = options.undoCallback;
let forFeedback = options.forFeedback;
@@ -199,7 +199,11 @@ var Overview = class {
}
_sessionUpdated() {
this.isDummy = !Main.sessionMode.hasOverview;
const { hasOverview } = Main.sessionMode;
if (!hasOverview)
this.hide();
this.isDummy = !hasOverview;
this._createOverview();
}
@@ -300,7 +304,7 @@ var Overview = class {
_resetWindowSwitchTimeout() {
if (this._windowSwitchTimeoutId != 0) {
Mainloop.source_remove(this._windowSwitchTimeoutId);
GLib.source_remove(this._windowSwitchTimeoutId);
this._windowSwitchTimeoutId = 0;
}
}
@@ -323,7 +327,9 @@ var Overview = class {
if (targetIsWindow) {
this._lastHoveredWindow = dragEvent.targetActor._delegate.metaWindow;
this._windowSwitchTimeoutId = Mainloop.timeout_add(DND_WINDOW_SWITCH_TIMEOUT,
this._windowSwitchTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
DND_WINDOW_SWITCH_TIMEOUT,
() => {
this._windowSwitchTimeoutId = 0;
Main.activateWindow(dragEvent.targetActor._delegate.metaWindow,
@@ -450,7 +456,7 @@ var Overview = class {
this._desktopFade.show();
this._desktopFade.ease({
opacity: 0,
mode: Clutter.Animates.EASE_OUT_QUAD,
mode: Clutter.AnimationMode.EASE_OUT_QUAD,
duration: ANIMATION_TIME
});
}
@@ -481,15 +487,13 @@ var Overview = class {
if (this._shown) {
let shouldBeModal = !this._inXdndDrag;
if (shouldBeModal) {
if (!this._modal) {
if (Main.pushModal(this._overview,
{ actionMode: Shell.ActionMode.OVERVIEW })) {
this._modal = true;
} else {
this.hide();
return false;
}
if (shouldBeModal && !this._modal) {
let actionMode = Shell.ActionMode.OVERVIEW;
if (Main.pushModal(this._overview, { actionMode })) {
this._modal = true;
} else {
this.hide();
return false;
}
}
} else {

View File

@@ -14,8 +14,8 @@ var SIDE_CONTROLS_ANIMATION_TIME = 160;
function getRtlSlideDirection(direction, actor) {
let rtl = (actor.text_direction == Clutter.TextDirection.RTL);
if (rtl)
direction = (direction == SlideDirection.LEFT) ?
SlideDirection.RIGHT : SlideDirection.LEFT;
direction = (direction == SlideDirection.LEFT)
? SlideDirection.RIGHT : SlideDirection.LEFT;
return direction;
}
@@ -67,8 +67,9 @@ var SlideLayout = GObject.registerClass({
// flags only determine what to do if the allocated box is bigger
// than the actor's box.
let realDirection = getRtlSlideDirection(this._direction, child);
let alignX = (realDirection == SlideDirection.LEFT) ? (availWidth - natWidth)
: (availWidth - natWidth * this._slideX);
let alignX = (realDirection == SlideDirection.LEFT)
? availWidth - natWidth
: availWidth - natWidth * this._slideX;
let actorBox = new Clutter.ActorBox();
actorBox.x1 = box.x1 + alignX + this._translationX;
@@ -248,6 +249,7 @@ var SlidingControl = class {
// selector; this means we can now safely set the full slide for
// the next page, since slideIn or slideOut might have been called,
// changing the visiblity
this.actor.remove_transition('@layout.slide-x');
this.layout.slide_x = this._getSlide();
this._updateTranslation();
}

View File

@@ -126,12 +126,14 @@ class AnimatedPageIndicators extends PageIndicators {
offset = children[0].width;
let isAnimationIn = animationDirection == AnimationDirection.IN;
let delay = isAnimationIn ? INDICATORS_ANIMATION_DELAY :
INDICATORS_ANIMATION_DELAY_OUT;
let delay = isAnimationIn
? INDICATORS_ANIMATION_DELAY
: INDICATORS_ANIMATION_DELAY_OUT;
let baseTime = isAnimationIn ? INDICATORS_BASE_TIME : INDICATORS_BASE_TIME_OUT;
let totalAnimationTime = baseTime + delay * this._nPages;
let maxTime = isAnimationIn ? INDICATORS_ANIMATION_MAX_TIME :
INDICATORS_ANIMATION_MAX_TIME_OUT;
let maxTime = isAnimationIn
? INDICATORS_ANIMATION_MAX_TIME
: INDICATORS_ANIMATION_MAX_TIME_OUT;
if (totalAnimationTime > maxTime)
delay -= (totalAnimationTime - maxTime) / this._nPages;

View File

@@ -3,7 +3,6 @@
const { Atk, Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Mainloop = imports.mainloop;
const Animation = imports.ui.animation;
const Config = imports.misc.config;
@@ -171,9 +170,13 @@ class AppMenu extends PopupMenu.PopupMenu {
let windows = this._app.get_windows();
windows.forEach(window => {
let title = window.title || this._app.get_name();
this._windowSection.addAction(title, event => {
let item = this._windowSection.addAction(title, event => {
Main.activateWindow(window, event.get_time());
});
let id = window.connect('notify::title', () => {
item.label.text = window.title || this._app.get_name();
});
item.connect('destroy', () => window.disconnect(id));
});
}
}
@@ -235,7 +238,10 @@ 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._spinner = new Animation.Spinner(PANEL_ICON_SIZE, true);
this._spinner = new Animation.Spinner(PANEL_ICON_SIZE, {
animate: true,
hideOnStop: true,
});
this._container.add_actor(this._spinner.actor);
let menu = new AppMenu(this);
@@ -451,8 +457,8 @@ class ActivitiesButton extends PanelMenu.Button {
return DND.DragMotionResult.CONTINUE;
if (this._xdndTimeOut != 0)
Mainloop.source_remove(this._xdndTimeOut);
this._xdndTimeOut = Mainloop.timeout_add(BUTTON_DND_ACTIVATION_TIMEOUT, () => {
GLib.source_remove(this._xdndTimeOut);
this._xdndTimeOut = GLib.timeout_add(GLib.PRIORITY_DEFAULT, BUTTON_DND_ACTIVATION_TIMEOUT, () => {
this._xdndToggleOverview();
});
GLib.Source.set_name_by_id(this._xdndTimeOut, '[gnome-shell] this._xdndToggleOverview');
@@ -496,7 +502,7 @@ class ActivitiesButton extends PanelMenu.Button {
if (pickedActor == this && Main.overview.shouldToggleByCornerOrButton())
Main.overview.toggle();
Mainloop.source_remove(this._xdndTimeOut);
GLib.source_remove(this._xdndTimeOut);
this._xdndTimeOut = 0;
return GLib.SOURCE_REMOVE;
}

View File

@@ -1,5 +1,5 @@
/* exported PointerA11yTimeout */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const { Clutter, GObject, Meta, St } = imports.gi;
const Main = imports.ui.main;
const Cairo = imports.cairo;

View File

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

View File

@@ -15,6 +15,7 @@ var Ornament = {
NONE: 0,
DOT: 1,
CHECK: 2,
HIDDEN: 3,
};
function isPopupMenuItemVisible(child) {
@@ -57,11 +58,9 @@ var PopupBaseMenuItem = GObject.registerClass({
Properties: {
'active': GObject.ParamSpec.boolean('active', 'active', 'active',
GObject.ParamFlags.READWRITE,
GObject.TYPE_BOOLEAN,
false),
'sensitive': GObject.ParamSpec.boolean('sensitive', 'sensitive', 'sensitive',
GObject.ParamFlags.READWRITE,
GObject.TYPE_BOOLEAN,
true),
},
Signals: {
@@ -69,12 +68,13 @@ var PopupBaseMenuItem = GObject.registerClass({
}
}, class PopupBaseMenuItem extends St.BoxLayout {
_init(params) {
params = Params.parse (params, { reactive: true,
activate: true,
hover: true,
style_class: null,
can_focus: true
});
params = Params.parse (params, {
reactive: true,
activate: true,
hover: true,
style_class: null,
can_focus: true,
});
super._init({ style_class: 'popup-menu-item',
reactive: params.reactive,
track_hover: params.reactive,
@@ -249,10 +249,12 @@ var PopupBaseMenuItem = GObject.registerClass({
} else if (ornament == Ornament.CHECK) {
this._ornamentLabel.text = '\u2713';
this.add_accessible_state(Atk.StateType.CHECKED);
} else if (ornament == Ornament.NONE) {
} else if (ornament == Ornament.NONE || ornament == Ornament.HIDDEN) {
this._ornamentLabel.text = '';
this.remove_accessible_state(Atk.StateType.CHECKED);
}
this._ornamentLabel.visible = ornament != Ornament.HIDDEN;
}
});
@@ -333,9 +335,10 @@ var PopupSwitchMenuItem = GObject.registerClass({
this._statusBin = new St.Bin({ x_align: St.Align.END });
this.add(this._statusBin, { expand: true, x_align: St.Align.END });
this._statusLabel = new St.Label({ text: '',
style_class: 'popup-status-menu-item'
});
this._statusLabel = new St.Label({
text: '',
style_class: 'popup-status-menu-item',
});
this._statusBin.child = this._switch;
}
@@ -425,6 +428,7 @@ var PopupMenuBase = class {
throw new TypeError(`Cannot instantiate abstract class ${this.constructor.name}`);
this.sourceActor = sourceActor;
this.focusActor = sourceActor;
this._parent = null;
if (styleClass !== undefined) {
@@ -549,7 +553,7 @@ var PopupMenuBase = class {
}
_connectItemSignals(menuItem) {
menuItem._activeChangeId = menuItem.connect('notify::active', (menuItem) => {
menuItem._activeChangeId = menuItem.connect('notify::active', menuItem => {
let active = menuItem.active;
if (active && this._activeMenuItem != menuItem) {
if (this._activeMenuItem)
@@ -613,8 +617,8 @@ var PopupMenuBase = class {
while (childBeforeIndex >= 0 && !isPopupMenuItemVisible(children[childBeforeIndex]))
childBeforeIndex--;
if (childBeforeIndex < 0
|| children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) {
if (childBeforeIndex < 0 ||
children[childBeforeIndex]._delegate instanceof PopupSeparatorMenuItem) {
menuItem.actor.hide();
return;
}
@@ -624,8 +628,8 @@ var PopupMenuBase = class {
while (childAfterIndex < children.length && !isPopupMenuItemVisible(children[childAfterIndex]))
childAfterIndex++;
if (childAfterIndex >= children.length
|| children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) {
if (childAfterIndex >= children.length ||
children[childAfterIndex]._delegate instanceof PopupSeparatorMenuItem) {
menuItem.actor.hide();
return;
}
@@ -718,10 +722,11 @@ var PopupMenuBase = class {
this.disconnect(openStateChangeId);
menuItem.disconnect(destroyId);
});
} else if (menuItem instanceof PopupBaseMenuItem)
} else if (menuItem instanceof PopupBaseMenuItem) {
this._connectItemSignals(menuItem);
else
} else {
throw TypeError("Invalid argument to PopupMenuBase.addMenuItem()");
}
menuItem._setParent(this);
@@ -799,6 +804,7 @@ var PopupMenu = class extends PopupMenuBase {
this._keyPressId = this.sourceActor.connect('key-press-event',
this._onKeyPress.bind(this));
this._systemModalOpenedId = 0;
this._openedSubMenu = null;
}
@@ -873,6 +879,11 @@ var PopupMenu = class extends PopupMenuBase {
if (this.isEmpty())
return;
if (!this._systemModalOpenedId) {
this._systemModalOpenedId =
Main.layoutManager.connect('system-modal-opened', () => this.close());
}
this.isOpen = true;
this._boxPointer.setPosition(this.sourceActor, this._arrowAlignment);
@@ -903,6 +914,11 @@ var PopupMenu = class extends PopupMenuBase {
destroy() {
if (this._keyPressId)
this.sourceActor.disconnect(this._keyPressId);
if (this._systemModalOpenedId)
Main.layoutManager.disconnect(this._systemModalOpenedId);
this._systemModalOpenedId = 0;
super.destroy();
}
};
@@ -1296,18 +1312,20 @@ var PopupMenuManager = class {
if (open) {
if (this.activeMenu)
this.activeMenu.close(BoxPointer.PopupAnimation.FADE);
this._grabHelper.grab({ actor: menu.actor, focus: menu.sourceActor,
onUngrab: isUser => {
this._closeMenu(isUser, menu);
} });
this._grabHelper.grab({
actor: menu.actor,
focus: menu.focusActor,
onUngrab: isUser => this._closeMenu(isUser, menu),
});
} else {
this._grabHelper.ungrab({ actor: menu.actor });
}
}
_changeMenu(newMenu) {
newMenu.open(this.activeMenu ? BoxPointer.PopupAnimation.FADE
: BoxPointer.PopupAnimation.FULL);
newMenu.open(this.activeMenu
? BoxPointer.PopupAnimation.FADE
: BoxPointer.PopupAnimation.FULL);
}
_onMenuSourceEnter(menu) {

View File

@@ -34,6 +34,12 @@ var Ripples = class Ripples {
this._ripple3.set_pivot_point(px, py);
}
destroy() {
this._ripple1.destroy();
this._ripple2.destroy();
this._ripple3.destroy();
}
_animRipple(ripple, delay, duration, startScale, startOpacity, finalScale) {
// We draw a ripple by using a source image and animating it scaling
// outwards and fading away. We want the ripples to move linearly
@@ -61,7 +67,7 @@ var Ripples = class Ripples {
delay,
duration,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => ripple.visible = false
onComplete: () => (ripple.visible = false)
});
}

View File

@@ -94,15 +94,17 @@ class RunDialog extends ModalDialog.ModalDialog {
this._errorBox.hide();
this.setButtons([{ action: this.close.bind(this),
label: _("Close"),
key: Clutter.Escape }]);
this.setButtons([{
action: this.close.bind(this),
label: _("Close"),
key: Clutter.Escape,
}]);
this._pathCompleter = new Gio.FilenameCompleter();
this._history = new History.HistoryManager({ gsettingsKey: HISTORY_KEY,
entry: this._entryText });
this._entryText.connect('activate', (o) => {
this._entryText.connect('activate', o => {
this.popModal();
this._run(o.get_text(),
Clutter.get_current_event().get_state() & Clutter.ModifierType.CONTROL_MASK);

View File

@@ -3,7 +3,6 @@
const { AccountsService, Clutter, Cogl, Gio, GLib,
GnomeDesktop, GObject, Meta, Shell, St } = imports.gi;
const Cairo = imports.cairo;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Background = imports.ui.background;
@@ -18,6 +17,8 @@ const MessageTray = imports.ui.messageTray;
const ShellDBus = imports.ui.shellDBus;
const SmartcardManager = imports.misc.smartcardManager;
const { adjustAnimationTime } = imports.ui.environment;
const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver';
const LOCK_ENABLED_KEY = 'lock-enabled';
const LOCK_DELAY_KEY = 'lock-delay';
@@ -52,11 +53,17 @@ var Clock = class {
this.actor = new St.BoxLayout({ style_class: 'screen-shield-clock',
vertical: true });
this._time = new St.Label({ style_class: 'screen-shield-clock-time' });
this._date = new St.Label({ style_class: 'screen-shield-clock-date' });
this._time = new St.Label({
style_class: 'screen-shield-clock-time',
x_align: Clutter.ActorAlign.CENTER,
});
this._date = new St.Label({
style_class: 'screen-shield-clock-date',
x_align: Clutter.ActorAlign.CENTER,
});
this.actor.add(this._time, { x_align: St.Align.MIDDLE });
this.actor.add(this._date, { x_align: St.Align.MIDDLE });
this.actor.add_child(this._time);
this.actor.add_child(this._date);
this._wallClock = new GnomeDesktop.WallClock({ time_only: true });
this._wallClock.connect('notify::clock', this._updateClock.bind(this));
@@ -92,7 +99,7 @@ var NotificationsBox = class {
style_class: 'screen-shield-notifications-container' });
this._scrollView.add_actor(this._notificationBox);
this.actor.add(this._scrollView, { x_fill: true, x_align: St.Align.START });
this.actor.add_child(this._scrollView);
this._sources = new Map();
Main.messageTray.getSources().forEach(source => {
@@ -133,10 +140,10 @@ var NotificationsBox = class {
_makeNotificationSource(source, box) {
let sourceActor = new MessageTray.SourceActor(source, SUMMARY_ICON_SIZE);
box.add(sourceActor, { y_fill: true });
box.add_child(sourceActor);
let textBox = new St.BoxLayout({ vertical: true });
box.add(textBox, { y_fill: false, y_align: St.Align.START });
box.add_child(textBox);
let title = new St.Label({ text: source.title,
style_class: 'screen-shield-notification-label' });
@@ -159,7 +166,7 @@ var NotificationsBox = class {
box.add(sourceBin);
let textBox = new St.BoxLayout({ vertical: true });
box.add(textBox, { y_fill: false, y_align: St.Align.START });
box.add_child(textBox);
let title = new St.Label({ text: source.title,
style_class: 'screen-shield-notification-label' });
@@ -174,8 +181,9 @@ var NotificationsBox = class {
let body = '';
if (n.bannerBodyText) {
body = n.bannerBodyMarkup ? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
body = n.bannerBodyMarkup
? n.bannerBodyText
: GLib.markup_escape_text(n.bannerBodyText, -1);
}
let label = new St.Label({ style_class: 'screen-shield-notification-count-text' });
@@ -220,7 +228,7 @@ var NotificationsBox = class {
obj.sourceBox = new St.BoxLayout({ style_class: 'screen-shield-notification-source',
x_expand: true });
this._showSource(source, obj, obj.sourceBox);
this._notificationBox.add(obj.sourceBox, { x_fill: false, x_align: St.Align.START });
this._notificationBox.add_child(obj.sourceBox);
obj.sourceCountChangedId = source.connect('count-updated', source => {
this._countChanged(source, obj);
@@ -430,13 +438,14 @@ var ScreenShield = class {
this.actor = Main.layoutManager.screenShieldGroup;
this._lockScreenState = MessageTray.State.HIDDEN;
this._lockScreenGroup = new St.Widget({ x_expand: true,
y_expand: true,
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup = new St.Widget({
x_expand: true,
y_expand: true,
reactive: true,
can_focus: true,
name: 'lockScreenGroup',
visible: false,
});
this._lockScreenGroup.connect('key-press-event',
this._onLockScreenKeyPress.bind(this));
this._lockScreenGroup.connect('scroll-event',
@@ -831,14 +840,16 @@ var ScreenShield = class {
if (shouldLock) {
let lockTimeout = Math.max(
STANDARD_FADE_TIME,
adjustAnimationTime(STANDARD_FADE_TIME),
this._settings.get_uint(LOCK_DELAY_KEY) * 1000);
this._lockTimeoutId = Mainloop.timeout_add(lockTimeout,
() => {
this._lockTimeoutId = 0;
this.lock(false);
return GLib.SOURCE_REMOVE;
});
this._lockTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
lockTimeout,
() => {
this._lockTimeoutId = 0;
this.lock(false);
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._lockTimeoutId, '[gnome-shell] this.lock');
}
@@ -913,8 +924,8 @@ var ScreenShield = class {
this._lockScreenGroup.hide();
if (this._dialog) {
this._dialog.actor.grab_key_focus();
this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
this._dialog.grab_key_focus();
this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
}
}
@@ -1028,7 +1039,7 @@ var ScreenShield = class {
this._arrowActiveWatchId = 0;
if (!this._arrowAnimationId) {
this._arrowAnimationId = Mainloop.timeout_add(6000, this._animateArrows.bind(this));
this._arrowAnimationId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, 6000, this._animateArrows.bind(this));
GLib.Source.set_name_by_id(this._arrowAnimationId, '[gnome-shell] this._animateArrows');
this._animateArrows();
}
@@ -1040,7 +1051,7 @@ var ScreenShield = class {
_pauseArrowAnimation() {
if (this._arrowAnimationId) {
Mainloop.source_remove(this._arrowAnimationId);
GLib.source_remove(this._arrowAnimationId);
this._arrowAnimationId = 0;
}
@@ -1050,7 +1061,7 @@ var ScreenShield = class {
_stopArrowAnimation() {
if (this._arrowAnimationId) {
Mainloop.source_remove(this._arrowAnimationId);
GLib.source_remove(this._arrowAnimationId);
this._arrowAnimationId = 0;
}
if (this._arrowActiveWatchId) {
@@ -1097,7 +1108,7 @@ var ScreenShield = class {
if (params.fadeToBlack && params.animateFade) {
// Take a beat
let id = Mainloop.timeout_add(MANUAL_FADE_TIME, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, MANUAL_FADE_TIME, () => {
this._activateFade(this._shortLightbox, MANUAL_FADE_TIME);
return GLib.SOURCE_REMOVE;
});
@@ -1128,16 +1139,13 @@ var ScreenShield = class {
vertical: true,
style_class: 'screen-shield-contents-box' });
this._clock = new Clock();
this._lockScreenContentsBox.add(this._clock.actor, { x_fill: true,
y_fill: true });
this._lockScreenContentsBox.add_child(this._clock.actor);
this._lockScreenContents.add_actor(this._lockScreenContentsBox);
this._notificationsBox = new NotificationsBox();
this._wakeUpScreenId = this._notificationsBox.connect('wake-up-screen', this._wakeUpScreen.bind(this));
this._lockScreenContentsBox.add(this._notificationsBox.actor, { x_fill: true,
y_fill: true,
expand: true });
this._lockScreenContentsBox.add_child(this._notificationsBox.actor);
this._hasLockScreen = true;
}
@@ -1240,7 +1248,7 @@ var ScreenShield = class {
}
if (this._lockTimeoutId != 0) {
Mainloop.source_remove(this._lockTimeoutId);
GLib.source_remove(this._lockTimeoutId);
this._lockTimeoutId = 0;
}

View File

@@ -116,8 +116,8 @@ var ScreenshotService = class {
try {
let [result, area, filenameUsed] =
screenshot.screenshot_area_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
this._onScreenshotComplete(
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
@@ -134,8 +134,8 @@ var ScreenshotService = class {
try {
let [result, area, filenameUsed] =
screenshot.screenshot_window_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
this._onScreenshotComplete(
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
@@ -152,8 +152,8 @@ var ScreenshotService = class {
try {
let [result, area, filenameUsed] =
screenshot.screenshot_finish(res);
this._onScreenshotComplete(result, area, filenameUsed,
flash, invocation);
this._onScreenshotComplete(
result, area, filenameUsed, flash, invocation);
} catch (e) {
invocation.return_gerror (e);
}
@@ -271,7 +271,7 @@ var SelectArea = class {
}
_onMotionEvent(actor, event) {
if (this._startX == -1 || this._startY == -1)
if (this._startX == -1 || this._startY == -1 || this._result)
return Clutter.EVENT_PROPAGATE;
[this._lastX, this._lastY] = event.get_coords();

View File

@@ -4,7 +4,6 @@
collectStatistics, runPerfScript */
const { Gio, GLib, Meta, Shell } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
const Params = imports.misc.params;
@@ -41,7 +40,7 @@ const { loadInterfaceXML } = imports.misc.fileUtils;
*/
function sleep(milliseconds) {
return new Promise(resolve => {
let id = Mainloop.timeout_add(milliseconds, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, milliseconds, () => {
resolve();
return GLib.SOURCE_REMOVE;
});
@@ -318,7 +317,7 @@ async function runPerfScript(scriptModule, outputFile) {
for (let step of scriptModule.run()) {
try {
await step;
await step; // eslint-disable-line no-await-in-loop
} catch (err) {
log(`Script failed: ${err}\n${err.stack}`);
Meta.exit(Meta.ExitCode.ERROR);

View File

@@ -158,10 +158,15 @@ var SearchResultsBase = class {
this._clipboard = St.Clipboard.get_default();
this._cancellable = new Gio.Cancellable();
this.actor.connect('destroy', this._onDestroy.bind(this));
}
destroy() {
this.actor.destroy();
}
_onDestroy() {
this._terms = [];
}
@@ -341,14 +346,30 @@ var GridSearchResults = class extends SearchResultsBase {
this._resultDisplayBin.set_child(this._bin);
}
_onDestroy() {
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
}
super._onDestroy();
}
updateSearch(...args) {
if (this._notifyAllocationId)
this.actor.disconnect(this._notifyAllocationId);
if (this._updateSearchLater) {
Meta.later_remove(this._updateSearchLater);
delete this._updateSearchLater;
}
// Make sure the maximum number of results calculated by
// _getMaxDisplayedResults() is updated after width changes.
this._notifyAllocationId = this.actor.connect('notify::allocation', () => {
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
if (this._updateSearchLater)
return;
this._updateSearchLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
delete this._updateSearchLater;
super.updateSearch(...args);
return GLib.SOURCE_REMOVE;
});
@@ -689,8 +710,9 @@ var SearchResults = class {
navigateFocus(direction) {
let rtl = this.actor.get_text_direction() == Clutter.TextDirection.RTL;
if (direction == St.DirectionType.TAB_BACKWARD ||
direction == (rtl ? St.DirectionType.RIGHT
: St.DirectionType.LEFT) ||
direction == (rtl
? St.DirectionType.RIGHT
: St.DirectionType.LEFT) ||
direction == St.DirectionType.UP) {
this.actor.navigate_focus(null, direction, false);
return;

View File

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

View File

@@ -151,9 +151,13 @@ var GnomeShell = class {
let connection = this._dbusImpl.get_connection();
let info = this._dbusImpl.get_info();
let params = { 'device-id': GLib.Variant.new('u', device.get_device_id()),
'device-node': GLib.Variant.new('s', device.get_device_node()),
'timestamp': GLib.Variant.new('u', timestamp),
'action-mode': GLib.Variant.new('u', Main.actionMode) };
let deviceNode = device.get_device_node();
if (deviceNode)
params['device-node'] = GLib.Variant.new('s', deviceNode);
connection.emit_signal(destination,
this._dbusImpl.get_object_path(),
info ? info.name : null,

View File

@@ -26,9 +26,10 @@ function _setButtonsForChoices(dialog, choices) {
for (let idx = 0; idx < choices.length; idx++) {
let button = idx;
buttons.unshift({ label: choices[idx],
action: () => dialog.emit('response', button)
});
buttons.unshift({
label: choices[idx],
action: () => dialog.emit('response', button),
});
}
dialog.setButtons(buttons);
@@ -201,7 +202,7 @@ var ShellMountOperation = class {
_onShowUnmountProgress(op, message, timeLeft, bytesLeft) {
if (!this._notifier)
this._notifier = new ShellUnmountNotifier();
if (bytesLeft == 0)
this._notifier.done(message);
else
@@ -358,7 +359,9 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._passwordEntry.clutter_text.set_password_char('\u25cf'); // ● U+25CF BLACK CIRCLE
ShellEntry.addContextMenu(this._passwordEntry, { isPassword: true });
this.setInitialKeyFocus(this._passwordEntry);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, true);
this._workSpinner = new Animation.Spinner(WORK_SPINNER_ICON_SIZE, {
animate: true,
});
this._passwordEntry.secondary_icon = this._workSpinner.actor;
if (rtl) {
@@ -387,24 +390,26 @@ var ShellMountPasswordDialog = GObject.registerClass({
this._rememberChoice = null;
}
this._defaultButtons = [{ label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape
},
{ label: _("Unlock"),
action: this._onUnlockButton.bind(this),
default: true
}];
this._defaultButtons = [{
label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape,
}, {
label: _("Unlock"),
action: this._onUnlockButton.bind(this),
default: true,
}];
this._usesKeyfilesButtons = [{ label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape
},
{ /* Translators: %s is the Disks application */
label: _("Open %s").format(disksApp.get_name()),
action: this._onOpenDisksButton.bind(this),
default: true
}];
this._usesKeyfilesButtons = [{
label: _("Cancel"),
action: this._onCancelButton.bind(this),
key: Clutter.Escape,
}, {
/* Translators: %s is the Disks application */
label: _("Open %s").format(disksApp.get_name()),
action: this._onOpenDisksButton.bind(this),
default: true,
}];
this.setButtons(this._defaultButtons);
}

View File

@@ -100,10 +100,15 @@ var Slider = GObject.registerClass({
_endDragging() {
if (this._dragging) {
if (this._releaseId)
if (this._releaseId) {
this.disconnect(this._releaseId);
if (this._motionId)
this._releaseId = 0;
}
if (this._motionId) {
this.disconnect(this._motionId);
this._motionId = 0;
}
if (this._grabbedSequence != null)
this._grabbedDevice.sequence_ungrab(this._grabbedSequence);

View File

@@ -2,7 +2,6 @@
/* exported ATIndicator */
const { Gio, GLib, GObject, St } = imports.gi;
const Mainloop = imports.mainloop;
const PanelMenu = imports.ui.panelMenu;
const PopupMenu = imports.ui.popupMenu;
@@ -96,7 +95,7 @@ class ATIndicator extends PanelMenu.Button {
if (this._syncMenuVisibilityIdle)
return;
this._syncMenuVisibilityIdle = Mainloop.idle_add(this._syncMenuVisibility.bind(this));
this._syncMenuVisibilityIdle = GLib.idle_add(GLib.PRIORITY_DEFAULT, this._syncMenuVisibility.bind(this));
GLib.Source.set_name_by_id(this._syncMenuVisibilityIdle, '[gnome-shell] this._syncMenuVisibility');
}
@@ -139,14 +138,14 @@ class ATIndicator extends PanelMenu.Button {
interfaceSettings.is_writable(KEY_ICON_THEME),
enabled => {
if (enabled) {
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_ICON_THEME, HIGH_CONTRAST_THEME);
interfaceSettings.set_string(KEY_GTK_THEME, HIGH_CONTRAST_THEME);
} else if (!hasHC) {
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
interfaceSettings.set_string(KEY_ICON_THEME, iconTheme);
interfaceSettings.set_string(KEY_GTK_THEME, gtkTheme);
} else {
interfaceSettings.reset(KEY_GTK_THEME);
interfaceSettings.reset(KEY_ICON_THEME);
interfaceSettings.reset(KEY_GTK_THEME);
}
});
@@ -180,8 +179,8 @@ class ATIndicator extends PanelMenu.Button {
settings.is_writable(KEY_TEXT_SCALING_FACTOR),
enabled => {
if (enabled)
settings.set_double(KEY_TEXT_SCALING_FACTOR,
DPI_FACTOR_LARGE);
settings.set_double(
KEY_TEXT_SCALING_FACTOR, DPI_FACTOR_LARGE);
else
settings.reset(KEY_TEXT_SCALING_FACTOR);
});

View File

@@ -13,8 +13,8 @@ const PanelMenu = imports.ui.panelMenu;
const SwitcherPopup = imports.ui.switcherPopup;
const Util = imports.misc.util;
const INPUT_SOURCE_TYPE_XKB = 'xkb';
const INPUT_SOURCE_TYPE_IBUS = 'ibus';
var INPUT_SOURCE_TYPE_XKB = 'xkb';
var INPUT_SOURCE_TYPE_IBUS = 'ibus';
var LayoutMenuItem = GObject.registerClass(
class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {
@@ -976,8 +976,8 @@ class InputSourceIndicator extends PanelMenu.Button {
item.prop = prop;
radioGroup.push(item);
item.radioGroup = radioGroup;
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED ?
PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
item.setOrnament(prop.get_state() == IBus.PropState.CHECKED
? PopupMenu.Ornament.DOT : PopupMenu.Ornament.NONE);
item.connect('activate', () => {
if (item.prop.get_state() == IBus.PropState.CHECKED)
return;

View File

@@ -168,8 +168,9 @@ var Indicator = class extends PanelMenu.SystemIndicator {
_updateMenuLabels() {
if (this._settings.get_boolean(ENABLED)) {
this._item.label.text = this._indicator.visible ? _("Location In Use")
: _("Location Enabled");
this._item.label.text = this._indicator.visible
? _("Location In Use")
: _("Location Enabled");
this._onOffAction.label.text = _("Disable");
} else {
this._item.label.text = _("Location Disabled");

View File

@@ -1,7 +1,6 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported NMApplet */
const { Clutter, Gio, GLib, GObject, NM, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const Animation = imports.ui.animation;
@@ -719,7 +718,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._updateSensitivity();
this._syncView();
this._scanTimeoutId = Mainloop.timeout_add_seconds(15, this._onScanTimeout.bind(this));
this._scanTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 15, this._onScanTimeout.bind(this));
GLib.Source.set_name_by_id(this._scanTimeoutId, '[gnome-shell] this._onScanTimeout');
this._onScanTimeout();
@@ -757,7 +756,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
}
if (this._scanTimeoutId) {
Mainloop.source_remove(this._scanTimeoutId);
GLib.source_remove(this._scanTimeoutId);
this._scanTimeoutId = 0;
}
}
@@ -874,7 +873,7 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._airplaneHeadline = new St.Label({ style_class: 'nm-dialog-airplane-headline headline' });
this._airplaneText = new St.Label({ style_class: 'nm-dialog-airplane-text' });
let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout });
let airplaneSubStack = new St.Widget({ layout_manager: new Clutter.BinLayout() });
this._airplaneButton = new St.Button({ style_class: 'modal-dialog-button button' });
this._airplaneButton.connect('clicked', () => {
if (this._rfkill.airplaneMode)
@@ -910,8 +909,8 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._client.activate_connection_async(connection, this._device, null, null, null);
} else {
let accessPoints = network.accessPoints;
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT)
|| (accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
if ((accessPoints[0]._secType == NMAccessPointSecurity.WPA2_ENT) ||
(accessPoints[0]._secType == NMAccessPointSecurity.WPA_ENT)) {
// 802.1x-enabled APs require further configuration, so they're
// handled in gnome-control-center
Util.spawn(['gnome-control-center', 'wifi', 'connect-8021x-wifi',
@@ -1074,13 +1073,14 @@ class NMWirelessDialog extends ModalDialog.ModalDialog {
this._resortItems();
} else {
network = { ssid: accessPoint.get_ssid(),
mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint),
connections: [],
item: null,
accessPoints: [accessPoint]
};
network = {
ssid: accessPoint.get_ssid(),
mode: accessPoint.mode,
security: this._getApSecurityType(accessPoint),
connections: [],
item: null,
accessPoints: [accessPoint],
};
network.ssidText = ssidToLabel(network.ssid);
this._checkConnections(network, accessPoint);
@@ -1676,7 +1676,7 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
'network-transmit-receive');
this._source.policy = new MessageTray.NotificationApplicationPolicy('gnome-network-panel');
this._source.connect('destroy', () => this._source = null);
this._source.connect('destroy', () => (this._source = null));
Main.messageTray.add(this._source);
}
}
@@ -1976,7 +1976,6 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
// or we get to full connectivity through other means
} else if (result == PortalHelperResult.COMPLETED) {
this._closeConnectivityCheck(path);
return;
} else if (result == PortalHelperResult.RECHECK) {
this._client.check_connectivity_async(null, (client, result) => {
try {

View File

@@ -58,10 +58,12 @@ var Indicator = class extends PanelMenu.SystemIndicator {
let visible = this._proxy.NightLightActive;
let disabled = this._proxy.DisabledUntilTomorrow;
this._item.label.text = disabled ? _("Night Light Disabled")
: _("Night Light On");
this._disableItem.label.text = disabled ? _("Resume")
: _("Disable Until Tomorrow");
this._item.label.text = disabled
? _("Night Light Disabled")
: _("Night Light On");
this._disableItem.label.text = disabled
? _("Resume")
: _("Disable Until Tomorrow");
this._item.visible = this._indicator.visible = visible;
}
};

View File

@@ -111,9 +111,12 @@ var Indicator = class extends PanelMenu.SystemIndicator {
let chargingState = this._proxy.State == UPower.DeviceState.CHARGING
? '-charging' : '';
let fillLevel = 10 * Math.floor(this._proxy.Percentage / 10);
let icon = this._proxy.State == UPower.DeviceState.FULLY_CHARGED
? 'battery-level-100-charged-symbolic'
: `battery-level-${fillLevel}${chargingState}-symbolic`;
let icon;
if (this._proxy.State == UPower.DeviceState.FULLY_CHARGED ||
fillLevel === 100)
icon = 'battery-level-100-charged-symbolic';
else
icon = `battery-level-${fillLevel}${chargingState}-symbolic`;
// Make sure we fall back to fallback-icon-name and not GThemedIcon's
// default fallbacks

View File

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

View File

@@ -156,12 +156,12 @@ var AuthRobot = class {
/* check if authorization is enabled in the daemon. if not
* we won't even bother authorizing, because we will only
* get an error back. The exact contents of AuthMode might
* get an error back. The exact contents of AuthMode might
* change in the future, but must contain AuthMode.ENABLED
* if it is enabled. */
if (!cli.authMode.split('|').includes(AuthMode.ENABLED))
return;
/* check if we should enroll the device */
let res = [false];
this.emit('enroll-device', dev, res);
@@ -260,7 +260,7 @@ var Indicator = class extends PanelMenu.SystemIndicator {
if (!this._source) {
this._source = new MessageTray.Source(_("Thunderbolt"),
'thunderbolt-symbolic');
this._source.connect('destroy', () => this._source = null);
this._source.connect('destroy', () => (this._source = null));
Main.messageTray.add(this._source);
}

View File

@@ -1,7 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported Indicator */
const { Clutter, Gio, Gvc, St } = imports.gi;
const { Clutter, Gio, GObject, Gvc, St } = imports.gi;
const Signals = imports.signals;
const Main = imports.ui.main;
@@ -36,7 +36,8 @@ var StreamSlider = class {
this._soundSettings.connect(`changed::${ALLOW_AMPLIFIED_VOLUME_KEY}`, this._amplifySettingsChanged.bind(this));
this._amplifySettingsChanged();
this._slider.connect('notify::value', this._sliderChanged.bind(this));
this._sliderChangedId = this._slider.connect('notify::value',
this._sliderChanged.bind(this));
this._slider.connect('drag-end', this._notifyVolumeChange.bind(this));
this._icon = new St.Icon({ style_class: 'popup-menu-icon' });
@@ -129,10 +130,16 @@ var StreamSlider = class {
this._volumeCancellable);
}
_changeSlider(value) {
GObject.signal_handler_block(this._slider, this._sliderChangedId);
this._slider.value = value;
GObject.signal_handler_unblock(this._slider, this._sliderChangedId);
}
_updateVolume() {
let muted = this._stream.is_muted;
this._slider.value = muted
? 0 : (this._stream.volume / this._control.get_vol_max_norm());
this._changeSlider(muted
? 0 : (this._stream.volume / this._control.get_vol_max_norm()));
this.emit('stream-updated');
}
@@ -221,9 +228,9 @@ var OutputStreamSlider = class extends StreamSlider {
}
_updateSliderIcon() {
this._icon.icon_name = (this._hasHeadphones ?
'audio-headphones-symbolic' :
'audio-speakers-symbolic');
this._icon.icon_name = (this._hasHeadphones
? 'audio-headphones-symbolic'
: 'audio-speakers-symbolic');
}
_portChanged() {
@@ -252,18 +259,17 @@ var InputStreamSlider = class extends StreamSlider {
_maybeShowInput() {
// only show input widgets if any application is recording audio
let showInput = false;
let recordingApps = this._control.get_source_outputs();
if (this._stream && recordingApps) {
for (let i = 0; i < recordingApps.length; i++) {
let outputStream = recordingApps[i];
let id = outputStream.get_application_id();
// but skip gnome-volume-control and pavucontrol
// (that appear as recording because they show the input level)
if (!id || (id != 'org.gnome.VolumeControl' && id != 'org.PulseAudio.pavucontrol')) {
showInput = true;
break;
}
}
if (this._stream) {
// skip gnome-volume-control and pavucontrol which appear
// as recording because they show the input level
let skippedApps = [
'org.gnome.VolumeControl',
'org.PulseAudio.pavucontrol'
];
showInput = this._control.get_source_outputs().some(output => {
return !skippedApps.includes(output.get_application_id());
});
}
this._showInput = showInput;

View File

@@ -2,7 +2,6 @@
/* exported SwitcherPopup, SwitcherList */
const { Clutter, GLib, GObject, Meta, St } = imports.gi;
const Mainloop = imports.mainloop;
const Main = imports.ui.main;
@@ -47,6 +46,9 @@ var SwitcherPopup = GObject.registerClass({
Main.uiGroup.add_actor(this);
this._systemModalOpenedId =
Main.layoutManager.connect('system-modal-opened', () => this.destroy());
this._haveModal = false;
this._modifierMask = 0;
@@ -142,13 +144,15 @@ var SwitcherPopup = GObject.registerClass({
// We delay showing the popup so that fast Alt+Tab users aren't
// disturbed by the popup briefly flashing.
this._initialDelayTimeoutId = Mainloop.timeout_add(POPUP_DELAY_TIMEOUT,
() => {
Main.osdWindowManager.hideAll();
this.opacity = 255;
this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
this._initialDelayTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
POPUP_DELAY_TIMEOUT,
() => {
Main.osdWindowManager.hideAll();
this.opacity = 255;
this._initialDelayTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
GLib.Source.set_name_by_id(this._initialDelayTimeoutId, '[gnome-shell] Main.osdWindow.cancel');
return true;
}
@@ -179,6 +183,14 @@ var SwitcherPopup = GObject.registerClass({
if (keysym == Clutter.Escape || keysym == Clutter.Tab)
this.fadeAndDestroy();
// Allow to explicitly select the current item; this is particularly
// useful for no-modifier popups
if (keysym === Clutter.KEY_space ||
keysym === Clutter.KEY_Return ||
keysym === Clutter.KEY_KP_Enter ||
keysym === Clutter.KEY_ISO_Enter)
this._finish(event.get_time());
return Clutter.EVENT_STOP;
}
@@ -249,9 +261,9 @@ var SwitcherPopup = GObject.registerClass({
this.mouseActive = false;
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
GLib.source_remove(this._motionTimeoutId);
this._motionTimeoutId = Mainloop.timeout_add(DISABLE_HOVER_TIMEOUT, this._mouseTimedOut.bind(this));
this._motionTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, DISABLE_HOVER_TIMEOUT, this._mouseTimedOut.bind(this));
GLib.Source.set_name_by_id(this._motionTimeoutId, '[gnome-shell] this._mouseTimedOut');
}
@@ -263,14 +275,16 @@ var SwitcherPopup = GObject.registerClass({
_resetNoModsTimeout() {
if (this._noModsTimeoutId != 0)
Mainloop.source_remove(this._noModsTimeoutId);
GLib.source_remove(this._noModsTimeoutId);
this._noModsTimeoutId = Mainloop.timeout_add(NO_MODS_TIMEOUT,
() => {
this._finish(global.get_current_time());
this._noModsTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
this._noModsTimeoutId = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
NO_MODS_TIMEOUT,
() => {
this._finish(global.display.get_current_time_roundtrip());
this._noModsTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
}
_popModal() {
@@ -301,12 +315,14 @@ var SwitcherPopup = GObject.registerClass({
_onDestroy() {
this._popModal();
Main.layoutManager.disconnect(this._systemModalOpenedId);
if (this._motionTimeoutId != 0)
Mainloop.source_remove(this._motionTimeoutId);
GLib.source_remove(this._motionTimeoutId);
if (this._initialDelayTimeoutId != 0)
Mainloop.source_remove(this._initialDelayTimeoutId);
GLib.source_remove(this._initialDelayTimeoutId);
if (this._noModsTimeoutId != 0)
Mainloop.source_remove(this._noModsTimeoutId);
GLib.source_remove(this._noModsTimeoutId);
}
_select(num) {
@@ -557,10 +573,10 @@ var SwitcherList = GObject.registerClass({
let leftPadding = this.get_theme_node().get_padding(St.Side.LEFT);
let rightPadding = this.get_theme_node().get_padding(St.Side.RIGHT);
let [, natScrollViewWidth] = this._scrollView.get_preferred_width(height);
let [minListWidth] = this._list.get_preferred_width(height);
let childBox = new Clutter.ActorBox();
let scrollable = natScrollViewWidth > width;
let scrollable = minListWidth > width;
this._scrollView.allocate(contentBox, flags);

View File

@@ -2,8 +2,7 @@
/* exported UnlockDialog */
const { AccountsService, Atk, Clutter,
Gdm, Gio, GLib, Meta, Shell, St } = imports.gi;
const Signals = imports.signals;
Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
@@ -13,15 +12,19 @@ const AuthPrompt = imports.gdm.authPrompt;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
var UnlockDialog = class {
constructor(parentActor) {
this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
style_class: 'login-dialog',
layout_manager: new Clutter.BoxLayout(),
visible: false });
var UnlockDialog = GObject.registerClass({
Signals: { 'failed': {} },
}, class UnlockDialog extends St.Widget {
_init(parentActor) {
super._init({
accessible_role: Atk.Role.WINDOW,
style_class: 'login-dialog',
layout_manager: new Clutter.BoxLayout(),
visible: false,
});
this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
parentActor.add_child(this.actor);
this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default();
this._userName = GLib.get_user_name();
@@ -32,7 +35,7 @@ var UnlockDialog = class {
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true });
this.actor.add_child(this._promptBox);
this.add_child(this._promptBox);
this._authPrompt = new AuthPrompt.AuthPrompt(new Gdm.Client(), AuthPrompt.AuthPromptMode.UNLOCK_ONLY);
this._authPrompt.connect('failed', this._fail.bind(this));
@@ -64,10 +67,12 @@ var UnlockDialog = class {
this._authPrompt.reset();
this._updateSensitivity(true);
Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic');
Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic');
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
}
_updateSensitivity(sensitive) {
@@ -106,9 +111,8 @@ var UnlockDialog = class {
this._authPrompt.cancel();
}
destroy() {
_onDestroy() {
this.popModal();
this.actor.destroy();
if (this._idleWatchId) {
this._idleMonitor.remove_watch(this._idleWatchId);
@@ -131,13 +135,16 @@ var UnlockDialog = class {
}
open(timestamp) {
this.actor.show();
this.show();
if (this._isModal)
return true;
if (!Main.pushModal(this.actor, { timestamp: timestamp,
actionMode: Shell.ActionMode.UNLOCK_SCREEN }))
let modalParams = {
timestamp,
actionMode: Shell.ActionMode.UNLOCK_SCREEN,
};
if (!Main.pushModal(this, modalParams))
return false;
this._isModal = true;
@@ -147,9 +154,8 @@ var UnlockDialog = class {
popModal(timestamp) {
if (this._isModal) {
Main.popModal(this.actor, timestamp);
Main.popModal(this, timestamp);
this._isModal = false;
}
}
};
Signals.addSignalMethods(UnlockDialog.prototype);
});

View File

@@ -309,12 +309,10 @@ var ViewSelector = class {
if (params.a11yFocus)
Main.ctrlAltTabManager.addGroup(params.a11yFocus, name, a11yIcon);
else
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon,
{ proxy: this.actor,
focusCallback: () => {
this._a11yFocusPage(page);
}
});
Main.ctrlAltTabManager.addGroup(actor, name, a11yIcon, {
proxy: this.actor,
focusCallback: () => this._a11yFocusPage(page),
});
page.hide();
this.actor.add_actor(page);
return page;
@@ -391,8 +389,8 @@ var ViewSelector = class {
}
_onShowAppsButtonToggled() {
this._showPage(this._showAppsButton.checked ?
this._appsPage : this._workspacesPage);
this._showPage(this._showAppsButton.checked
? this._appsPage : this._workspacesPage);
}
_onStageKeyPress(actor, event) {
@@ -426,8 +424,9 @@ var ViewSelector = class {
}
_searchCancelled() {
this._showPage(this._showAppsButton.checked ? this._appsPage
: this._workspacesPage);
this._showPage(this._showAppsButton.checked
? this._appsPage
: this._workspacesPage);
// Leave the entry focused when it doesn't have any text;
// when replacing a selected search term, Clutter emits
@@ -578,6 +577,7 @@ var ViewSelector = class {
if (event.type() == Clutter.EventType.BUTTON_PRESS) {
let source = event.get_source();
if (source != this._text &&
this._text.has_key_focus() &&
this._text.text == '' &&
!this._text.has_preedit () &&
!Main.layoutManager.keyboardBox.contains(source)) {

View File

@@ -2,7 +2,6 @@
/* exported WindowManager */
const { Clutter, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const AltTab = imports.ui.altTab;
@@ -17,6 +16,7 @@ const PadOsd = imports.ui.padOsd;
const EdgeDragAction = imports.ui.edgeDragAction;
const CloseDialog = imports.ui.closeDialog;
const SwitchMonitor = imports.ui.switchMonitor;
const IBusManager = imports.misc.ibusManager;
const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -70,13 +70,13 @@ class DisplayChangeDialog extends ModalDialog.ModalDialog {
action: this._onSuccess.bind(this),
default: true });
this._timeoutId = Mainloop.timeout_add(ONE_SECOND, this._tick.bind(this));
this._timeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, ONE_SECOND, this._tick.bind(this));
GLib.Source.set_name_by_id(this._timeoutId, '[gnome-shell] this._tick');
}
close(timestamp) {
if (this._timeoutId > 0) {
Mainloop.source_remove(this._timeoutId);
GLib.source_remove(this._timeoutId);
this._timeoutId = 0;
}
@@ -187,6 +187,9 @@ var WorkspaceTracker = class {
let workspaceManager = global.workspace_manager;
workspaceManager.connect('notify::n-workspaces',
this._nWorkspacesChanged.bind(this));
workspaceManager.connect('workspaces-reordered', () => {
this._workspaces.sort((a, b) => a.index() - b.index());
});
global.window_manager.connect('switch-workspace',
this._queueCheckWorkspaces.bind(this));
@@ -280,9 +283,9 @@ var WorkspaceTracker = class {
keepWorkspaceAlive(workspace, duration) {
if (workspace._keepAliveId)
Mainloop.source_remove(workspace._keepAliveId);
GLib.source_remove(workspace._keepAliveId);
workspace._keepAliveId = Mainloop.timeout_add(duration, () => {
workspace._keepAliveId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, duration, () => {
workspace._keepAliveId = 0;
this._queueCheckWorkspaces();
return GLib.SOURCE_REMOVE;
@@ -293,7 +296,7 @@ var WorkspaceTracker = class {
_windowRemoved(workspace, window) {
workspace._lastRemovedWindow = window;
this._queueCheckWorkspaces();
let id = Mainloop.timeout_add(LAST_WINDOW_GRACE_TIME, () => {
let id = GLib.timeout_add(GLib.PRIORITY_DEFAULT, LAST_WINDOW_GRACE_TIME, () => {
if (workspace._lastRemovedWindow == window) {
workspace._lastRemovedWindow = null;
this._queueCheckWorkspaces();
@@ -630,9 +633,9 @@ var AppSwitchAction = GObject.registerClass({
let nPoints = this.get_n_current_points();
let event = this.get_last_event (nPoints - 1);
if (nPoints == 3)
if (nPoints == 3) {
this._longPressStartTime = event.get_time();
else if (nPoints == 4) {
} else if (nPoints == 4) {
// Check whether the 4th finger press happens after a 3-finger long press,
// this only needs to be checked on the first 4th finger press
if (this._longPressStartTime != null &&
@@ -697,23 +700,24 @@ var WindowManager = class {
constructor() {
this._shellwm = global.window_manager;
this._minimizing = [];
this._unminimizing = [];
this._mapping = [];
this._resizing = [];
this._destroying = [];
this._minimizing = new Set();
this._unminimizing = new Set();
this._mapping = new Set();
this._resizing = new Set();
this._resizePending = new Set();
this._destroying = new Set();
this._movingWindow = null;
this._dimmedWindows = [];
this._skippedActors = [];
this._skippedActors = new Set();
this._allowedKeybindings = {};
this._isWorkspacePrepended = false;
this._switchData = null;
this._shellwm.connect('kill-switch-workspace', (shellwm) => {
this._shellwm.connect('kill-switch-workspace', shellwm => {
if (this._switchData) {
if (this._switchData.inProgress)
this._switchWorkspaceDone(shellwm);
@@ -1022,7 +1026,6 @@ var WindowManager = class {
(proxy, error) => {
if (error) {
log(error.message);
return;
}
});
@@ -1041,6 +1044,15 @@ var WindowManager = class {
}
});
global.display.connect('x11-display-opened', () => {
IBusManager.getIBusManager().restartDaemon(['--xim']);
Shell.util_start_systemd_unit('gnome-session-x11-services.target', 'fail');
});
global.display.connect('x11-display-closing', () => {
Shell.util_stop_systemd_unit('gnome-session-x11-services.target', 'fail');
IBusManager.getIBusManager().restartDaemon();
});
Main.overview.connect('showing', () => {
for (let i = 0; i < this._dimmedWindows.length; i++)
this._undimWindow(this._dimmedWindows[i]);
@@ -1106,7 +1118,7 @@ var WindowManager = class {
_showPadOsd(display, device, settings, imagePath, editionMode, monitorIndex) {
this._currentPadOsd = new PadOsd.PadOsd(device, settings, imagePath, editionMode, monitorIndex);
this._currentPadOsd.connect('closed', () => this._currentPadOsd = null);
this._currentPadOsd.connect('closed', () => (this._currentPadOsd = null));
return this._currentPadOsd.actor;
}
@@ -1201,9 +1213,41 @@ var WindowManager = class {
if (!Meta.prefs_get_dynamic_workspaces())
return;
let newWs = workspaceManager.append_new_workspace(
false, global.get_current_time());
workspaceManager.reorder_workspace(newWs, pos);
workspaceManager.append_new_workspace(false, global.get_current_time());
let windows = global.get_window_actors().map(a => a.meta_window);
// To create a new workspace, we slide all the windows on workspaces
// below us to the next workspace, leaving a blank workspace for us
// to recycle.
windows.forEach(window => {
// If the window is attached to an ancestor, we don't need/want
// to move it
if (window.get_transient_for() != null)
return;
// Same for OR windows
if (window.is_override_redirect())
return;
// Sticky windows don't need moving, in fact moving would
// unstick them
if (window.on_all_workspaces)
return;
// Windows on workspaces below pos don't need moving
let index = window.get_workspace().index();
if (index < pos)
return;
window.change_workspace_by_index(index + 1, true);
});
// If the new workspace was inserted before the active workspace,
// activate the workspace to which its windows went
let activeIndex = workspaceManager.get_active_workspace_index();
if (activeIndex >= pos) {
let newWs = workspaceManager.get_workspace_by_index(activeIndex + 1);
this._blockAnimations = true;
newWs.activate(global.get_current_time());
this._blockAnimations = false;
}
}
keepWorkspaceAlive(workspace, duration) {
@@ -1214,7 +1258,7 @@ var WindowManager = class {
}
skipNextEffect(actor) {
this._skippedActors.push(actor);
this._skippedActors.add(actor);
}
setCustomKeybindingHandler(name, modes, handler) {
@@ -1243,7 +1287,7 @@ var WindowManager = class {
}
_shouldAnimateActor(actor, types) {
if (this._removeEffect(this._skippedActors, actor))
if (this._skippedActors.delete(actor))
return false;
if (!this._shouldAnimate())
@@ -1256,15 +1300,6 @@ var WindowManager = class {
return types.includes(type);
}
_removeEffect(list, actor) {
let idx = list.indexOf(actor);
if (idx != -1) {
list.splice(idx, 1);
return true;
}
return false;
}
_minimizeWindow(shellwm, actor) {
let types = [Meta.WindowType.NORMAL,
Meta.WindowType.MODAL_DIALOG,
@@ -1276,7 +1311,7 @@ var WindowManager = class {
actor.set_scale(1.0, 1.0);
this._minimizing.push(actor);
this._minimizing.add(actor);
if (actor.meta_window.is_monitor_sized()) {
actor.ease({
@@ -1330,7 +1365,7 @@ var WindowManager = class {
}
_minimizeWindowDone(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
if (this._minimizing.delete(actor)) {
actor.remove_all_transitions();
actor.set_scale(1.0, 1.0);
actor.set_opacity(255);
@@ -1341,7 +1376,7 @@ var WindowManager = class {
}
_minimizeWindowOverwritten(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
if (this._minimizing.delete(actor)) {
shellwm.completed_minimize(actor);
}
}
@@ -1355,7 +1390,7 @@ var WindowManager = class {
return;
}
this._unminimizing.push(actor);
this._unminimizing.add(actor);
if (actor.meta_window.is_monitor_sized()) {
actor.opacity = 0;
@@ -1412,7 +1447,7 @@ var WindowManager = class {
}
_unminimizeWindowDone(shellwm, actor) {
if (this._removeEffect(this._unminimizing, actor)) {
if (this._unminimizing.delete(actor)) {
actor.remove_all_transitions();
actor.set_scale(1.0, 1.0);
actor.set_opacity(255);
@@ -1423,7 +1458,7 @@ var WindowManager = class {
}
_unminimizeWindowOverwritten(shellwm, actor) {
if (this._removeEffect(this._unminimizing, actor)) {
if (this._unminimizing.delete(actor)) {
shellwm.completed_unminimize(actor);
}
}
@@ -1458,6 +1493,7 @@ var WindowManager = class {
this._clearAnimationInfo(actor);
});
this._resizePending.add(actor);
actor.__animationInfo = { clone: actorClone,
oldRect: oldFrameRect,
destroyId: destroyId };
@@ -1466,7 +1502,7 @@ var WindowManager = class {
_sizeChangedWindow(shellwm, actor) {
if (!actor.__animationInfo)
return;
if (this._resizing.includes(actor))
if (this._resizing.has(actor))
return;
let actorClone = actor.__animationInfo.clone;
@@ -1476,7 +1512,8 @@ var WindowManager = class {
let scaleX = targetRect.width / sourceRect.width;
let scaleY = targetRect.height / sourceRect.height;
this._resizing.push(actor);
this._resizePending.delete(actor);
this._resizing.add(actor);
// Now scale and fade out the clone
actorClone.ease({
@@ -1529,7 +1566,7 @@ var WindowManager = class {
}
_sizeChangeWindowDone(shellwm, actor) {
if (this._removeEffect(this._resizing, actor)) {
if (this._resizing.delete(actor)) {
actor.remove_all_transitions();
actor.scale_x = 1.0;
actor.scale_y = 1.0;
@@ -1537,10 +1574,13 @@ var WindowManager = class {
actor.translation_y = 0;
this._clearAnimationInfo(actor);
}
if (this._resizePending.delete(actor))
this._shellwm.completed_size_change(actor);
}
_sizeChangeWindowOverwritten(shellwm, actor) {
if (this._removeEffect(this._resizing, actor))
if (this._resizing.delete(actor))
this._clearAnimationInfo(actor);
}
@@ -1633,7 +1673,7 @@ var WindowManager = class {
actor.scale_y = 0.05;
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
this._mapping.add(actor);
actor.ease({
opacity: 255,
@@ -1655,7 +1695,7 @@ var WindowManager = class {
actor.scale_y = 0;
actor.opacity = 0;
actor.show();
this._mapping.push(actor);
this._mapping.add(actor);
actor.ease({
opacity: 255,
@@ -1673,12 +1713,11 @@ var WindowManager = class {
break;
default:
shellwm.completed_map(actor);
return;
}
}
_mapWindowDone(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
if (this._mapping.delete(actor)) {
actor.remove_all_transitions();
actor.opacity = 255;
actor.set_pivot_point(0, 0);
@@ -1691,7 +1730,7 @@ var WindowManager = class {
}
_mapWindowOverwrite(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
if (this._mapping.delete(actor)) {
shellwm.completed_map(actor);
}
}
@@ -1721,7 +1760,7 @@ var WindowManager = class {
switch (actor.meta_window.window_type) {
case Meta.WindowType.NORMAL:
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
this._destroying.add(actor);
actor.ease({
opacity: 0,
@@ -1735,7 +1774,7 @@ var WindowManager = class {
case Meta.WindowType.MODAL_DIALOG:
case Meta.WindowType.DIALOG:
actor.set_pivot_point(0.5, 0.5);
this._destroying.push(actor);
this._destroying.add(actor);
if (window.is_attached_dialog()) {
let parent = window.get_transient_for();
@@ -1754,12 +1793,11 @@ var WindowManager = class {
break;
default:
shellwm.completed_destroy(actor);
return;
}
}
_destroyWindowDone(shellwm, actor) {
if (this._removeEffect(this._destroying, actor)) {
if (this._destroying.delete(actor)) {
let parent = actor.get_meta_window().get_transient_for();
if (parent && actor._parentDestroyId) {
parent.disconnect(actor._parentDestroyId);

View File

@@ -178,7 +178,7 @@ var WindowMenu = class extends PopupMenu.PopupMenu {
}
let waitId = 0;
let id = global.display.connect('grab-op-end', (display) => {
let id = global.display.connect('grab-op-end', display => {
display.disconnect(id);
GLib.source_remove(waitId);
@@ -224,7 +224,7 @@ var WindowMenuManager = class {
this._sourceActor.set_position(rect.x, rect.y);
this._sourceActor.show();
menu.open(BoxPointer.PopupAnimation.NONE);
menu.open(BoxPointer.PopupAnimation.FADE);
menu.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
menu.connect('open-state-changed', (menu_, isOpen) => {
if (isOpen)

View File

@@ -2,7 +2,6 @@
/* exported Workspace */
const { Atk, Clutter, GLib, GObject, Meta, Pango, Shell, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
const DND = imports.ui.dnd;
@@ -57,17 +56,16 @@ class WindowCloneLayout extends Clutter.LayoutManager {
// has an extra set of "padding" around it that we need to trim
// down.
// The outer rect (from which we compute the bounding box)
// paradoxically is the smaller rectangle, containing the positions
// of the visible frame. The input rect contains everything,
// including the invisible border padding.
let inputRect = window.get_buffer_rect();
// The bounding box is based on the (visible) frame rect, while
// the buffer rect contains everything, including the invisible
// border padding.
let bufferRect = window.get_buffer_rect();
let box = new Clutter.ActorBox();
box.set_origin(inputRect.x - this._boundingBox.x,
inputRect.y - this._boundingBox.y);
box.set_size(inputRect.width, inputRect.height);
box.set_origin(bufferRect.x - this._boundingBox.x,
bufferRect.y - this._boundingBox.y);
box.set_size(bufferRect.width, bufferRect.height);
return box;
}
@@ -83,8 +81,8 @@ class WindowCloneLayout extends Clutter.LayoutManager {
vfunc_allocate(container, box, flags) {
container.get_children().forEach(child => {
let realWindow;
if (child == container._delegate._windowClone)
realWindow = container._delegate.realWindow;
if (child == container._windowClone)
realWindow = container.realWindow;
else
realWindow = child.source;
@@ -104,7 +102,7 @@ var WindowClone = GObject.registerClass({
'show-chrome': {},
'size-changed': {}
},
}, class WindowClone extends St.Widget {
}, class WorkspaceWindowClone extends St.Widget {
_init(realWindow, workspace) {
this.realWindow = realWindow;
this.metaWindow = realWindow.meta_window;
@@ -159,6 +157,8 @@ var WindowClone = GObject.registerClass({
this.x = this._boundingBox.x;
this.y = this._boundingBox.y;
this._computeWindowCenter();
let clickAction = new Clutter.ClickAction();
clickAction.connect('clicked', this._onClicked.bind(this));
clickAction.connect('long-press', this._onLongPress.bind(this));
@@ -301,6 +301,18 @@ var WindowClone = GObject.registerClass({
this.layout_manager.boundingBox = rect;
}
get windowCenter() {
return this._windowCenter;
}
_computeWindowCenter() {
let box = this.realWindow.get_allocation_box();
this._windowCenter = new Clutter.Point({
x: box.get_x() + box.get_width() / 2,
y: box.get_y() + box.get_height() / 2,
});
}
// Find the actor just below us, respecting reparenting done by DND code
getActualStackAbove() {
if (this._stackAbove == null)
@@ -354,6 +366,11 @@ var WindowClone = GObject.registerClass({
this.metaWindow._delegate = null;
this._delegate = null;
if (this._longPressLater) {
Meta.later_remove(this._longPressLater);
delete this._longPressLater;
}
if (this.inDrag) {
this.emit('drag-end');
this.inDrag = false;
@@ -388,9 +405,13 @@ var WindowClone = GObject.registerClass({
let event = Clutter.get_current_event();
this._dragTouchSequence = event.get_event_sequence();
if (this._longPressLater)
return true;
// A click cancels a long-press before any click handler is
// run - make sure to not start a drag in that case
Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
this._longPressLater = Meta.later_add(Meta.LaterType.BEFORE_REDRAW, () => {
delete this._longPressLater;
if (this._selected)
return;
let [x, y] = action.get_coords();
@@ -405,8 +426,6 @@ var WindowClone = GObject.registerClass({
_onDragBegin(_draggable, _time) {
this._dragSlot = this._slot;
[this.dragOrigX, this.dragOrigY] = this.get_position();
this.dragOrigScale = this.scale_x;
this.inDrag = true;
this.emit('drag-begin');
}
@@ -416,7 +435,7 @@ var WindowClone = GObject.registerClass({
}
acceptDrop(source, actor, x, y, time) {
this._workspace.acceptDrop(source, actor, x, y, time);
return this._workspace.acceptDrop(source, actor, x, y, time);
}
_onDragCancelled(_draggable, _time) {
@@ -461,7 +480,8 @@ var WindowOverlay = class {
this.border = new St.Bin({ style_class: 'window-clone-border' });
this.title = new St.Label({ style_class: 'window-caption',
text: this._getCaption() });
text: this._getCaption(),
reactive: true });
this.title.clutter_text.ellipsize = Pango.EllipsizeMode.END;
windowClone.label_actor = this.title;
@@ -486,7 +506,6 @@ var WindowOverlay = class {
this.closeButton.hide();
// Don't block drop targets
Shell.util_set_hidden_from_pick(this.title, true);
Shell.util_set_hidden_from_pick(this.border, true);
parentActor.add_actor(this.border);
@@ -628,7 +647,7 @@ var WindowOverlay = class {
_onDestroy() {
if (this._idleHideOverlayId > 0) {
Mainloop.source_remove(this._idleHideOverlayId);
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = 0;
}
this._windowClone.metaWindow.disconnect(this._updateCaptionId);
@@ -679,25 +698,28 @@ var WindowOverlay = class {
}
_onHideChrome() {
if (this._idleHideOverlayId == 0) {
this._idleHideOverlayId = Mainloop.timeout_add(WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
}
if (this._idleHideOverlayId > 0)
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_OVERLAY_IDLE_HIDE_TIMEOUT, this._idleHideOverlay.bind(this));
GLib.Source.set_name_by_id(this._idleHideOverlayId, '[gnome-shell] this._idleHideOverlay');
}
_idleHideOverlay() {
this._idleHideOverlayId = 0;
if (this.closeButton['has-pointer'] ||
this.title['has-pointer'])
return GLib.SOURCE_CONTINUE;
if (!this._windowClone['has-pointer'] &&
!this.closeButton['has-pointer'])
if (!this._windowClone['has-pointer'])
this._animateInvisible();
this._idleHideOverlayId = 0;
return GLib.SOURCE_REMOVE;
}
hideOverlay() {
if (this._idleHideOverlayId > 0) {
Mainloop.source_remove(this._idleHideOverlayId);
GLib.source_remove(this._idleHideOverlayId);
this._idleHideOverlayId = 0;
}
this.closeButton.hide();
@@ -896,7 +918,7 @@ var LayoutStrategy = class {
computeWindowSlots(layout, area) {
this._computeRowSizes(layout);
let { rows: rows, scale: scale } = layout;
let { rows, scale } = layout;
let slots = [];
@@ -939,7 +961,7 @@ var LayoutStrategy = class {
y += row.height * row.additionalScale + this._rowSpacing;
}
compensation = compensation / 2;
compensation /= 2;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
@@ -971,7 +993,7 @@ var LayoutStrategy = class {
var UnalignedLayoutStrategy = class extends LayoutStrategy {
_computeRowSizes(layout) {
let { rows: rows, scale: scale } = layout;
let { rows, scale } = layout;
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
row.width = row.fullWidth * scale + (row.windows.length - 1) * this._columnSpacing;
@@ -995,11 +1017,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
_sortRow(row) {
// Sort windows horizontally to minimize travel distance.
// This affects in what order the windows end up in a row.
row.windows.sort((a, b) => {
let aCenter = a.realWindow.x + a.realWindow.width / 2;
let bCenter = b.realWindow.x + b.realWindow.width / 2;
return aCenter - bCenter;
});
row.windows.sort((a, b) => a.windowCenter.x - b.windowCenter.x);
}
computeLayout(windows, layout) {
@@ -1018,11 +1036,7 @@ var UnalignedLayoutStrategy = class extends LayoutStrategy {
// Sort windows vertically to minimize travel distance.
// This affects what rows the windows get placed in.
let sortedWindows = windows.slice();
sortedWindows.sort((a, b) => {
let aCenter = a.realWindow.y + a.realWindow.height / 2;
let bCenter = b.realWindow.y + b.realWindow.height / 2;
return aCenter - bCenter;
});
sortedWindows.sort((a, b) => a.windowCenter.y - b.windowCenter.y);
let windowIdx = 0;
for (let i = 0; i < numRows; i++) {
@@ -1090,10 +1104,8 @@ const WorkspaceActor = GObject.registerClass(
class WorkspaceActor extends St.Widget {
vfunc_get_focus_chain() {
return this.get_children().filter(c => c.visible).sort((a, b) => {
let cloneA = (a._delegate && a._delegate instanceof WindowClone) ? a._delegate : null;
let cloneB = (b._delegate && b._delegate instanceof WindowClone) ? b._delegate : null;
if (cloneA && cloneB)
return cloneA.slotId - cloneB.slotId;
if (a instanceof WindowClone && b instanceof WindowClone)
return a.slotId - b.slotId;
return 0;
});
@@ -1263,7 +1275,7 @@ var Workspace = class {
_realRecalculateWindowPositions(flags) {
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1473,7 +1485,7 @@ var Workspace = class {
// remove old handler
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1483,7 +1495,7 @@ var Workspace = class {
this._cursorY = y;
this._currentLayout = null;
this._repositionWindowsId = Mainloop.timeout_add(WINDOW_REPOSITIONING_DELAY,
this._repositionWindowsId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, WINDOW_REPOSITIONING_DELAY,
this._delayedWindowRepositioning.bind(this));
GLib.Source.set_name_by_id(this._repositionWindowsId, '[gnome-shell] this._delayedWindowRepositioning');
}
@@ -1497,7 +1509,7 @@ var Workspace = class {
if (!win) {
// Newly-created windows are added to a workspace before
// the compositor finds out about them...
let id = Mainloop.idle_add(() => {
let id = GLib.idle_add(GLib.PRIORITY_DEFAULT, () => {
if (this.actor &&
metaWin.get_compositor_private() &&
metaWin.get_workspace() == this.metaWorkspace)
@@ -1643,7 +1655,7 @@ var Workspace = class {
this._windows[i].remove_all_transitions();
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1728,7 +1740,7 @@ var Workspace = class {
this._windows[i].remove_all_transitions();
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
this._overviewHiddenId = Main.overview.connect('hidden', this._doneLeavingOverview.bind(this));
@@ -1789,7 +1801,7 @@ var Workspace = class {
global.display.disconnect(this._windowLeftMonitorId);
if (this._repositionWindowsId > 0) {
Mainloop.source_remove(this._repositionWindowsId);
GLib.source_remove(this._repositionWindowsId);
this._repositionWindowsId = 0;
}
@@ -1978,7 +1990,7 @@ var Workspace = class {
}
_onCloneSelected(clone, time) {
let wsIndex = undefined;
let wsIndex;
if (this.metaWorkspace)
wsIndex = this.metaWorkspace.index();
Main.activateWindow(clone.metaWindow, time, wsIndex);
@@ -1988,13 +2000,20 @@ var Workspace = class {
handleDragOver(source, _actor, _x, _y, _time) {
if (source.realWindow && !this._isMyWindow(source.realWindow))
return DND.DragMotionResult.MOVE_DROP;
if (source.shellWorkspaceLaunch)
if (source.app && source.app.can_open_new_window())
return DND.DragMotionResult.COPY_DROP;
if (!source.app && source.shellWorkspaceLaunch)
return DND.DragMotionResult.COPY_DROP;
return DND.DragMotionResult.CONTINUE;
}
acceptDrop(source, actor, x, y, time) {
let workspaceManager = global.workspace_manager;
let workspaceIndex = this.metaWorkspace
? this.metaWorkspace.index()
: workspaceManager.get_active_workspace_index();
if (source.realWindow) {
let win = source.realWindow;
if (this._isMyWindow(win))
@@ -2016,12 +2035,18 @@ var Workspace = class {
if (metaWindow.get_monitor() != this.monitorIndex)
metaWindow.move_to_monitor(this.monitorIndex);
let workspaceManager = global.workspace_manager;
let index = this.metaWorkspace ? this.metaWorkspace.index() : workspaceManager.get_active_workspace_index();
metaWindow.change_workspace_by_index(index, false);
metaWindow.change_workspace_by_index(workspaceIndex, false);
return true;
} else if (source.shellWorkspaceLaunch) {
source.shellWorkspaceLaunch({ workspace: this.metaWorkspace ? this.metaWorkspace.index() : -1,
} else if (source.app && source.app.can_open_new_window()) {
if (source.animateLaunchAtPos)
source.animateLaunchAtPos(actor.x, actor.y);
source.app.open_new_window(workspaceIndex);
return true;
} else if (!source.app && source.shellWorkspaceLaunch) {
// While unused in our own drag sources, shellWorkspaceLaunch allows
// extensions to define custom actions for their drag sources.
source.shellWorkspaceLaunch({ workspace: workspaceIndex,
timestamp: time });
return true;
}

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