Compare commits

...

63 Commits

Author SHA1 Message Date
9f7b1bd677 Bump version to 3.34.2
Update NEWS.
2019-12-11 21:03:50 +01:00
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
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
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
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
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
56902542c7 Update Malay translation 2019-12-09 10:24:46 +00:00
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
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
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
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
35bb67bb2f Update Chinese (Taiwan) translation 2019-11-27 16:07:32 +00:00
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
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
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
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
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
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
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
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
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
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
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
363336e4a1 Update Brazilian Portuguese translation 2019-11-25 14:12:45 +00:00
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
ef726bf313 Update Russian translation 2019-11-11 19:27:16 +00:00
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
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
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
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
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
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
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
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
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
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
40 changed files with 4910 additions and 2740 deletions

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

42
NEWS
View File

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

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

@ -1061,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%);
@ -1153,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 {
@ -1209,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

@ -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) {

View File

@ -3,7 +3,7 @@
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 Main = imports.ui.main;
@ -127,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

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

@ -3,6 +3,8 @@
const { Clutter, GLib, Gio, St } = imports.gi;
const Params = imports.misc.params;
var ANIMATED_ICON_UPDATE_TIMEOUT = 16;
var SPINNER_ANIMATION_TIME = 300;
var SPINNER_ANIMATION_DELAY = 1000;
@ -131,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() {
@ -146,6 +158,7 @@ var Spinner = class extends AnimatedIcon {
play() {
this.actor.remove_all_transitions();
this.actor.show();
if (this._animate) {
super.play();
@ -169,11 +182,18 @@ var Spinner = class extends AnimatedIcon {
opacity: 0,
duration: SPINNER_ANIMATION_TIME,
mode: Clutter.AnimationMode.LINEAR,
onComplete: () => super.stop()
onComplete: () => {
super.stop();
if (this._hideOnStop)
this.actor.hide();
},
});
} else {
this.actor.opacity = 0;
super.stop();
if (this._hideOnStop)
this.actor.hide();
}
}
};

View File

@ -40,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';
@ -97,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;
@ -173,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
@ -308,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);
@ -335,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');
@ -377,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() {
@ -425,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
@ -450,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);
});
@ -463,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
@ -648,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);
@ -662,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);
@ -730,29 +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);
}
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() {
@ -760,6 +808,8 @@ var AllView = class AllView extends BaseAppView {
dragMotion: this._onDragMotion.bind(this)
};
DND.addDragMonitor(this._dragMonitor);
this._eventBlocker.visible = false;
}
_onDragMotion(dragEvent) {
@ -782,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) {
@ -815,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();
@ -918,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);
}
@ -1349,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);
};
@ -1387,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);
}
@ -1487,8 +1534,6 @@ var FolderIcon = class FolderIcon {
dragMotion: this._onDragMotion.bind(this),
};
DND.addDragMonitor(this._dragMonitor);
this._parentView.inhibitEventBlocker();
}
_onDragMotion(dragEvent) {
@ -1504,7 +1549,6 @@ var FolderIcon = class FolderIcon {
_onDragEnd() {
this.actor.remove_style_pseudo_class('drop');
this._parentView.uninhibitEventBlocker();
DND.removeDragMonitor(this._dragMonitor);
}
@ -1994,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;
@ -2021,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));
@ -2051,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(
@ -2075,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);

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,7 @@ var CloseDialog = GObject.registerClass({
this._dialog = null;
this._removeWindowEffect();
dialog.ease({
dialog._dialog.ease({
scale_y: 0,
mode: Clutter.AnimationMode.LINEAR,
duration: DIALOG_TRANSITION_TIME,

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);

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,7 +95,9 @@ 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);
@ -144,8 +136,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 +155,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 +217,10 @@ var AuthenticationDialog = GObject.registerClass({
}
_onAuthenticateButtonPressed() {
this._onEntryActivate();
if (this._mode === DialogMode.CONFIRM)
this._initiateSession();
else
this._onEntryActivate();
}
_onSessionCompleted(session, gainedAuthorization) {
@ -247,7 +251,7 @@ var AuthenticationDialog = GObject.registerClass({
}
/* Try and authenticate again */
this.performAuthentication();
this._initiateSession();
}
}
@ -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

@ -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

@ -109,8 +109,6 @@ function _easeActor(actor, params) {
actor.set_easing_mode(params.mode);
delete params.mode;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
@ -124,6 +122,11 @@ function _easeActor(actor, params) {
let transition = animatedProps.map(p => actor.get_transition(p))
.find(t => t !== null);
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
@ -145,8 +148,6 @@ function _easeActorProperty(actor, propName, target, params) {
if (actor instanceof Clutter.Actor && !actor.mapped)
duration = 0;
Meta.disable_unredirect_for_display(global.display);
let cleanup = () => Meta.enable_unredirect_for_display(global.display);
let callback = _makeEaseCallback(params, cleanup);
@ -157,6 +158,7 @@ function _easeActorProperty(actor, propName, target, params) {
let [obj, prop] = _getPropertyTarget(actor, propName);
obj[prop] = target;
Meta.disable_unredirect_for_display(global.display);
callback(true);
return;
@ -172,6 +174,11 @@ function _easeActorProperty(actor, propName, target, params) {
transition.set_to(target);
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));
}

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;
@ -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();
}

View File

@ -466,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 (names.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) {
}
}
}

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() {

View File

@ -127,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);
}
@ -135,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);
}
@ -169,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);

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

@ -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();

View File

@ -170,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));
});
}
}
@ -234,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);

View File

@ -804,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;
}
@ -878,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);
@ -908,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();
}
};

View File

@ -17,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';
@ -51,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));
@ -91,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 => {
@ -132,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' });
@ -158,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' });
@ -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);
@ -832,7 +840,7 @@ 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 = GLib.timeout_add(
GLib.PRIORITY_DEFAULT,
@ -1131,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;
}

View File

@ -359,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) {

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

@ -46,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;
@ -180,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;
}
@ -270,7 +281,7 @@ var SwitcherPopup = GObject.registerClass({
GLib.PRIORITY_DEFAULT,
NO_MODS_TIMEOUT,
() => {
this._finish(global.get_current_time());
this._finish(global.display.get_current_time_roundtrip());
this._noModsTimeoutId = 0;
return GLib.SOURCE_REMOVE;
});
@ -304,6 +315,8 @@ var SwitcherPopup = GObject.registerClass({
_onDestroy() {
this._popModal();
Main.layoutManager.disconnect(this._systemModalOpenedId);
if (this._motionTimeoutId != 0)
GLib.source_remove(this._motionTimeoutId);
if (this._initialDelayTimeoutId != 0)
@ -560,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

@ -700,16 +700,17 @@ 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 = {};
@ -1257,7 +1258,7 @@ var WindowManager = class {
}
skipNextEffect(actor) {
this._skippedActors.push(actor);
this._skippedActors.add(actor);
}
setCustomKeybindingHandler(name, modes, handler) {
@ -1286,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())
@ -1299,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,
@ -1319,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({
@ -1373,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);
@ -1384,7 +1376,7 @@ var WindowManager = class {
}
_minimizeWindowOverwritten(shellwm, actor) {
if (this._removeEffect(this._minimizing, actor)) {
if (this._minimizing.delete(actor)) {
shellwm.completed_minimize(actor);
}
}
@ -1398,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;
@ -1455,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);
@ -1466,7 +1458,7 @@ var WindowManager = class {
}
_unminimizeWindowOverwritten(shellwm, actor) {
if (this._removeEffect(this._unminimizing, actor)) {
if (this._unminimizing.delete(actor)) {
shellwm.completed_unminimize(actor);
}
}
@ -1501,6 +1493,7 @@ var WindowManager = class {
this._clearAnimationInfo(actor);
});
this._resizePending.add(actor);
actor.__animationInfo = { clone: actorClone,
oldRect: oldFrameRect,
destroyId: destroyId };
@ -1509,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;
@ -1519,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({
@ -1572,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;
@ -1580,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);
}
@ -1676,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,
@ -1698,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,
@ -1720,7 +1717,7 @@ var WindowManager = class {
}
_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);
@ -1733,7 +1730,7 @@ var WindowManager = class {
}
_mapWindowOverwrite(shellwm, actor) {
if (this._removeEffect(this._mapping, actor)) {
if (this._mapping.delete(actor)) {
shellwm.completed_map(actor);
}
}
@ -1763,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,
@ -1777,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();
@ -1800,7 +1797,7 @@ var WindowManager = class {
}
_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

@ -157,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));
@ -299,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)
@ -1003,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) {
@ -1026,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++) {

View File

@ -1,5 +1,5 @@
project('gnome-shell', 'c',
version: '3.34.1',
version: '3.34.2',
meson_version: '>= 0.47.0',
license: 'GPLv2+'
)
@ -31,6 +31,7 @@ polkit_req = '>= 0.100'
schemas_req = '>= 3.33.1'
startup_req = '>= 0.11'
ibus_req = '>= 1.5.2'
gnome_desktop_req = '>= 3.32'
bt_req = '>= 3.9.0'
gst_req = '>= 0.11.92'
@ -97,6 +98,7 @@ startup_dep = dependency('libstartup-notification-1.0', version: startup_req)
ibus_dep = dependency('ibus-1.0', version: ibus_req)
x11_dep = dependency('x11')
schemas_dep = dependency('gsettings-desktop-schemas', version: schemas_req)
gnome_desktop_dep = dependency('gnome-desktop-3.0', version: gnome_desktop_req)
bt_dep = dependency('gnome-bluetooth-1.0', version: bt_req, required: false)
gst_dep = dependency('gstreamer-1.0', version: gst_req, required: false)
@ -177,6 +179,11 @@ cdata.set('HAVE__NL_TIME_FIRST_WEEKDAY',
cc.has_header_symbol('langinfo.h', '_NL_TIME_FIRST_WEEKDAY')
)
# New API added in gnome-desktop3 3.34.2/3.35.2
cdata.set('HAVE_GNOME_SYSTEMD',
cc.has_header('libgnome-desktop/gnome-systemd.h', dependencies: gnome_desktop_dep)
)
cdata.set('HAVE_FDWALK',
cc.has_function('fdwalk')
)

3512
po/ms.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1393
po/ru.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -105,7 +105,8 @@ typedef struct
} CollectAppointmentsData;
static time_t
get_time_from_property (ICalComponent *icomp,
get_time_from_property (ECalClient *cal,
ICalComponent *icomp,
ICalPropertyKind prop_kind,
ICalTime * (* get_prop_func) (ICalProperty *prop),
ICalTimezone *default_zone)
@ -124,12 +125,14 @@ get_time_from_property (ICalComponent *icomp,
param = i_cal_property_get_first_parameter (prop, I_CAL_TZID_PARAMETER);
if (param)
timezone = i_cal_timezone_get_builtin_timezone_from_tzid (i_cal_parameter_get_tzid (param));
timezone = e_timezone_cache_get_timezone (E_TIMEZONE_CACHE (cal), i_cal_parameter_get_tzid (param));
else if (i_cal_time_is_utc (itt))
timezone = i_cal_timezone_get_utc_timezone ();
else
timezone = default_zone;
i_cal_time_set_timezone (itt, timezone);
retval = i_cal_time_as_timet_with_zone (itt, timezone);
g_clear_object (&param);
@ -180,27 +183,32 @@ get_ical_description (ICalComponent *icomp)
}
static inline time_t
get_ical_start_time (ICalComponent *icomp,
get_ical_start_time (ECalClient *cal,
ICalComponent *icomp,
ICalTimezone *default_zone)
{
return get_time_from_property (icomp,
return get_time_from_property (cal,
icomp,
I_CAL_DTSTART_PROPERTY,
i_cal_property_get_dtstart,
default_zone);
}
static inline time_t
get_ical_end_time (ICalComponent *icomp,
get_ical_end_time (ECalClient *cal,
ICalComponent *icomp,
ICalTimezone *default_zone)
{
return get_time_from_property (icomp,
return get_time_from_property (cal,
icomp,
I_CAL_DTEND_PROPERTY,
i_cal_property_get_dtend,
default_zone);
}
static gboolean
get_ical_is_all_day (ICalComponent *icomp,
get_ical_is_all_day (ECalClient *cal,
ICalComponent *icomp,
time_t start_time,
ICalTimezone *default_zone)
{
@ -226,7 +234,7 @@ get_ical_is_all_day (ICalComponent *icomp,
start_tm->tm_hour != 0)
return FALSE;
if ((end_time = get_ical_end_time (icomp, default_zone)))
if ((end_time = get_ical_end_time (cal, icomp, default_zone)))
return (end_time - start_time) % 86400 == 0;
prop = i_cal_component_get_first_property (icomp, I_CAL_DURATION_PROPERTY);
@ -244,20 +252,24 @@ get_ical_is_all_day (ICalComponent *icomp,
}
static inline time_t
get_ical_due_time (ICalComponent *icomp,
get_ical_due_time (ECalClient *cal,
ICalComponent *icomp,
ICalTimezone *default_zone)
{
return get_time_from_property (icomp,
return get_time_from_property (cal,
icomp,
I_CAL_DUE_PROPERTY,
i_cal_property_get_due,
default_zone);
}
static inline time_t
get_ical_completed_time (ICalComponent *icomp,
get_ical_completed_time (ECalClient *cal,
ICalComponent *icomp,
ICalTimezone *default_zone)
{
return get_time_from_property (icomp,
return get_time_from_property (cal,
icomp,
I_CAL_COMPLETED_PROPERTY,
i_cal_property_get_completed,
default_zone);
@ -411,9 +423,10 @@ calendar_appointment_init (CalendarAppointment *appointment,
appointment->summary = get_ical_summary (icomp);
appointment->description = get_ical_description (icomp);
appointment->color_string = get_source_color (cal);
appointment->start_time = get_ical_start_time (icomp, default_zone);
appointment->end_time = get_ical_end_time (icomp, default_zone);
appointment->is_all_day = get_ical_is_all_day (icomp,
appointment->start_time = get_ical_start_time (cal, icomp, default_zone);
appointment->end_time = get_ical_end_time (cal, icomp, default_zone);
appointment->is_all_day = get_ical_is_all_day (cal,
icomp,
appointment->start_time,
default_zone);
}
@ -430,6 +443,18 @@ calendar_appointment_new (ICalComponent *icomp,
return appointment;
}
static time_t
timet_from_ical_time (ICalTime *time,
ICalTimezone *default_zone)
{
ICalTimezone *timezone = NULL;
timezone = i_cal_time_get_timezone (time);
if (timezone == NULL)
timezone = default_zone;
return i_cal_time_as_timet_with_zone (time, timezone);
}
static gboolean
generate_instances_cb (ICalComponent *icomp,
ICalTime *instance_start,
@ -456,8 +481,8 @@ generate_instances_cb (ICalComponent *icomp,
}
occurrence = g_new0 (CalendarOccurrence, 1);
occurrence->start_time = i_cal_time_as_timet_with_zone (instance_start, default_zone);
occurrence->end_time = i_cal_time_as_timet_with_zone (instance_end, default_zone);
occurrence->start_time = timet_from_ical_time (instance_start, default_zone);
occurrence->end_time = timet_from_ical_time (instance_end, default_zone);
occurrence->rid = e_cal_util_component_get_recurid_as_string (icomp);
appointment->occurrences = g_slist_append (appointment->occurrences, occurrence);

View File

@ -142,9 +142,10 @@ settings_list_remove (GSettings *settings,
n_values = g_strv_length (list);
new_value = g_new0 (char *, n_values);
for (i = 0, s = (const char **)list; i < n_values; i++, s++)
i = 0;
for (s = (const char **)list; *s != NULL; s++)
if (!g_str_equal (*s, value))
new_value[i] = g_strdup (*s);
new_value[i++] = g_strdup (*s);
g_settings_set_strv (settings, key, (const char **)new_value);
g_settings_sync ();

View File

@ -192,7 +192,7 @@ libshell_no_gir_sources += dbus_generated
libshell = library('gnome-shell',
sources: libshell_gir_sources + libshell_no_gir_sources,
dependencies: gnome_shell_deps + [libshell_menu_dep, libst_dep, mutter_dep, m_dep],
dependencies: gnome_shell_deps + [libshell_menu_dep, libst_dep, mutter_dep, gnome_desktop_dep, m_dep],
include_directories: [conf_inc, st_inc, include_directories('tray')],
c_args: gnome_shell_cflags,
link_with: [libtray],

View File

@ -29,6 +29,11 @@
#include <meta/meta-workspace-manager.h>
#include <meta/meta-x11-display.h>
#ifdef HAVE_GNOME_SYSTEMD
#define GNOME_DESKTOP_USE_UNSTABLE_API
#include <libgnome-desktop/gnome-systemd.h>
#endif
/* Memory report bits */
#ifdef HAVE_MALLINFO
#include <malloc.h>
@ -43,6 +48,7 @@
#include "shell-perf-log.h"
#include "shell-window-tracker.h"
#include "shell-wm.h"
#include "shell-util.h"
#include "st.h"
static ShellGlobal *the_object = NULL;
@ -1308,6 +1314,32 @@ shell_global_get_current_time (ShellGlobal *global)
return clutter_get_current_event_time ();
}
#ifdef HAVE_GNOME_SYSTEMD
static void
shell_global_app_launched_cb (GAppLaunchContext *context,
GAppInfo *info,
GVariant *platform_data,
gpointer user_data)
{
gint32 pid;
const gchar *app_name;
if (!g_variant_lookup (platform_data, "pid", "i", &pid))
return;
app_name = g_app_info_get_id (info);
if (app_name == NULL)
app_name = g_app_info_get_executable (info);
/* Start async request; we don't care about the result */
gnome_start_systemd_scope (app_name,
pid,
NULL,
NULL,
NULL, NULL, NULL);
}
#endif
/**
* shell_global_create_app_launch_context:
* @global: A #ShellGlobal
@ -1343,6 +1375,13 @@ shell_global_create_app_launch_context (ShellGlobal *global,
meta_launch_context_set_workspace (context, ws);
#ifdef HAVE_GNOME_SYSTEMD
g_signal_connect (context,
"launched",
G_CALLBACK (shell_global_app_launched_cb),
NULL);
#endif
return (GAppLaunchContext *) context;
}

View File

@ -457,7 +457,6 @@ grab_window_screenshot (ClutterActor *stage,
ClutterActor *window_actor;
gfloat actor_x, actor_y;
MetaRectangle rect;
cairo_rectangle_int_t clip;
window_actor = CLUTTER_ACTOR (meta_window_get_compositor_private (window));
clutter_actor_get_position (window_actor, &actor_x, &actor_y);
@ -467,16 +466,10 @@ grab_window_screenshot (ClutterActor *stage,
if (!priv->include_frame)
meta_window_frame_rect_to_client_rect (window, &rect, &rect);
priv->screenshot_area.x = rect.x;
priv->screenshot_area.y = rect.y;
clip.x = rect.x - (gint) actor_x;
clip.y = rect.y - (gint) actor_y;
clip.width = priv->screenshot_area.width = rect.width;
clip.height = priv->screenshot_area.height = rect.height;
priv->screenshot_area = rect;
priv->image = meta_window_actor_get_image (META_WINDOW_ACTOR (window_actor),
&clip);
NULL);
priv->datetime = g_date_time_new_now_local ();
if (priv->include_cursor)

View File

@ -43,6 +43,8 @@ struct _StTextureCachePrivate
GHashTable *keyed_cache; /* char * -> ClutterImage* */
GHashTable *keyed_surface_cache; /* char * -> cairo_surface_t* */
GHashTable *used_scales; /* Set: double */
/* Presently this is used to de-duplicate requests for GIcons and async URIs. */
GHashTable *outstanding_requests; /* char * -> AsyncTextureLoadData * */
@ -181,6 +183,7 @@ st_texture_cache_init (StTextureCache *self)
g_str_equal,
g_free,
(GDestroyNotify) cairo_surface_destroy);
self->priv->used_scales = g_hash_table_new (g_double_hash, g_double_equal);
self->priv->outstanding_requests = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
@ -199,6 +202,7 @@ st_texture_cache_dispose (GObject *object)
g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy);
g_clear_pointer (&self->priv->used_scales, g_hash_table_destroy);
g_clear_pointer (&self->priv->outstanding_requests, g_hash_table_destroy);
g_clear_pointer (&self->priv->file_monitors, g_hash_table_destroy);
@ -1062,6 +1066,22 @@ load_from_pixbuf (GdkPixbuf *pixbuf,
return actor;
}
static void
hash_table_remove_with_scales (GHashTable *hash,
GList *scales,
const char *base_key)
{
GList *l;
for (l = scales; l; l = l->next)
{
double scale = *((double *)l->data);
g_autofree char *key = NULL;
key = g_strdup_printf ("%s%f", base_key, scale);
g_hash_table_remove (hash, key);
}
}
static void
file_changed_cb (GFileMonitor *monitor,
GFile *file,
@ -1072,18 +1092,22 @@ file_changed_cb (GFileMonitor *monitor,
StTextureCache *cache = user_data;
char *key;
guint file_hash;
g_autoptr (GList) scales = NULL;
if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
return;
file_hash = g_file_hash (file);
scales = g_hash_table_get_keys (cache->priv->used_scales);
key = g_strdup_printf (CACHE_PREFIX_FILE "%u", file_hash);
g_hash_table_remove (cache->priv->keyed_cache, key);
hash_table_remove_with_scales (cache->priv->keyed_cache, scales, key);
g_free (key);
key = g_strdup_printf (CACHE_PREFIX_FILE_FOR_CAIRO "%u", file_hash);
g_hash_table_remove (cache->priv->keyed_surface_cache, key);
hash_table_remove_with_scales (cache->priv->keyed_surface_cache, scales, key);
g_free (key);
g_signal_emit (cache, signals[TEXTURE_FILE_CHANGED], 0, file);
@ -1418,7 +1442,10 @@ st_texture_cache_load_file_sync_to_cogl_texture (StTextureCache *cache,
goto out;
if (policy == ST_TEXTURE_CACHE_POLICY_FOREVER)
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), image);
{
g_hash_table_insert (cache->priv->keyed_cache, g_strdup (key), image);
g_hash_table_insert (cache->priv->used_scales, &resource_scale, &resource_scale);
}
}
/* Because the texture is loaded synchronously, we won't call
@ -1467,6 +1494,7 @@ st_texture_cache_load_file_sync_to_cairo_surface (StTextureCache *cache,
cairo_surface_reference (surface);
g_hash_table_insert (cache->priv->keyed_surface_cache,
g_strdup (key), surface);
g_hash_table_insert (cache->priv->used_scales, &resource_scale, &resource_scale);
}
}
else