import gnome-shell-3.32.2-20.el8

This commit is contained in:
CentOS Sources 2020-11-03 06:45:57 -05:00 committed by Andrew Lukoshko
parent 2230511b0d
commit 0a8425e83d
13 changed files with 2405 additions and 24 deletions

View File

@ -0,0 +1,65 @@
From f03c6a870820543901331d1920b7b3e423813d2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 27 Feb 2020 13:46:44 -0800
Subject: [PATCH 1/6] environment: reduce calls to g_time_zone_new_local()
Creating a new GTimeZone for the local timezone can be quite expensive if
done repeatedly. It requires an open(), mmap(), and parsing of
/etc/localtime.
This patch was provided by Florian, and I've tested it as far back as
3.28.4 to ensure that we are really reducing the number of open() calls
on the compositor thread.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/1051
Signed-off-by: Christian Hergert <chergert@redhat.com>
---
js/ui/environment.js | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/js/ui/environment.js b/js/ui/environment.js
index e22ec7402..f3f2d17c7 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -11,6 +11,9 @@ imports.gi.versions.TelepathyLogger = '0.2';
const { Clutter, GLib, Shell, St } = imports.gi;
const Gettext = imports.gettext;
+const System = imports.system;
+
+let _localTimeZone = null;
// We can't import shell JS modules yet, because they may have
// variable initializations, etc, that depend on init() already having
@@ -110,9 +113,26 @@ function init() {
}
};
+ // Override to clear our own timezone cache as well
+ const origClearDateCaches = System.clearDateCaches;
+ System.clearDateCaches = function () {
+ _localTimeZone = null;
+ origClearDateCaches();
+ };
+
// Work around https://bugzilla.mozilla.org/show_bug.cgi?id=508783
Date.prototype.toLocaleFormat = function(format) {
- return Shell.util_format_date(format, this.getTime());
+ if (_localTimeZone === null)
+ _localTimeZone = GLib.TimeZone.new_local();
+
+ let dt = GLib.DateTime.new(_localTimeZone,
+ this.getYear(),
+ this.getMonth() + 1,
+ this.getDate(),
+ this.getHours(),
+ this.getMinutes(),
+ this.getSeconds());
+ return dt ? dt.format(format) : '';
};
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
--
2.26.2

View File

@ -0,0 +1,36 @@
From fb0a9a60ab8f1c0dd96e789969ab9b6e48a9fce4 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 21 Jul 2020 16:33:04 +0200
Subject: [PATCH] popupMenu: Handle keypress if numlock is enabled
On Wayland, navigating menus with the keyboard would not open drop-down
menus when NumLock is enabled.
That's old issue (gnome-shell#550) that was not completely fixed with
commit 88556226 because the lock mask needs to be filtered out in
_onKeyPress() as well.
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/550
---
js/ui/popupMenu.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/js/ui/popupMenu.js b/js/ui/popupMenu.js
index 6de081ce81..9835face19 100644
--- a/js/ui/popupMenu.js
+++ b/js/ui/popupMenu.js
@@ -801,9 +801,10 @@ var PopupMenu = class extends PopupMenuBase {
let state = event.get_state();
- // if user has a modifier down (except capslock)
+ // if user has a modifier down (except capslock and numlock)
// then don't handle the key press here
state &= ~Clutter.ModifierType.LOCK_MASK;
+ state &= ~Clutter.ModifierType.MOD2_MASK;
state &= Clutter.ModifierType.MODIFIER_MASK;
if (state)
--
2.26.2

View File

@ -0,0 +1,94 @@
From 1bf28eea64056846547ec33d783c7f2e0dad78a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 22 May 2020 22:53:39 +0200
Subject: [PATCH] st/texture-cache: Cancel pending requests on icon-theme
changes
As outlined in commit 36b8dcbe07, we can end up with wrong icons
if the icon theme changes right after a GTK theme change to/from
HighContrast triggered a theme reload.
That's because when we reload icons for the new icon theme, there
are already pending requests due to the icon-style change; those
requests are simply re-used for the new icons, with the existing
icon infos from the old theme.
The above commit applied a simple work-around by changing the
icon theme before the GTK theme, but that only works for the
HighContrast switch in our own UI.
It turns out that Settings also uses the "wrong" order, so the
issue still reproduces with the Universal Access panel.
So instead of relying on everything changing the settings in the
order we expect, cancel all ongoing requests on icon-theme changes.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1277
---
src/st/st-texture-cache.c | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index 35e9d036f..6dc351282 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -48,6 +48,8 @@ struct _StTextureCachePrivate
/* File monitors to evict cache data on changes */
GHashTable *file_monitors; /* char * -> GFileMonitor * */
+
+ GCancellable *cancellable;
};
static void st_texture_cache_dispose (GObject *object);
@@ -152,6 +154,9 @@ on_icon_theme_changed (StSettings *settings,
{
g_autofree gchar *theme;
+ g_cancellable_cancel (cache->priv->cancellable);
+ g_cancellable_reset (cache->priv->cancellable);
+
st_texture_cache_evict_icons (cache);
g_object_get (settings, "gtk-icon-theme", &theme, NULL);
@@ -186,6 +191,8 @@ st_texture_cache_init (StTextureCache *self)
self->priv->file_monitors = g_hash_table_new_full (g_file_hash, (GEqualFunc) g_file_equal,
g_object_unref, g_object_unref);
+ self->priv->cancellable = g_cancellable_new ();
+
on_icon_theme_changed (settings, NULL, self);
}
@@ -194,8 +201,11 @@ st_texture_cache_dispose (GObject *object)
{
StTextureCache *self = (StTextureCache*)object;
+ g_cancellable_cancel (self->priv->cancellable);
+
g_clear_object (&self->priv->settings);
g_clear_object (&self->priv->icon_theme);
+ g_clear_object (&self->priv->cancellable);
g_clear_pointer (&self->priv->keyed_cache, g_hash_table_destroy);
g_clear_pointer (&self->priv->keyed_surface_cache, g_hash_table_destroy);
@@ -675,11 +685,14 @@ load_texture_async (StTextureCache *cache,
gtk_icon_info_load_symbolic_async (data->icon_info,
&foreground_color, &success_color,
&warning_color, &error_color,
- NULL, on_symbolic_icon_loaded, data);
+ cache->priv->cancellable,
+ on_symbolic_icon_loaded, data);
}
else
{
- gtk_icon_info_load_icon_async (data->icon_info, NULL, on_icon_loaded, data);
+ gtk_icon_info_load_icon_async (data->icon_info,
+ cache->priv->cancellable,
+ on_icon_loaded, data);
}
}
else
--
2.26.2

View File

@ -0,0 +1,33 @@
From 189add05c07fe9d9bed6c1399b30e51a4a934bd3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 2 Mar 2020 13:46:04 +0100
Subject: [PATCH 2/6] environment: Fix date conversion
This is a regression from commit 06b690ff21204:
GLib.DateTime.new() expects the full four-digit year, so passing
the abbreviated year from Date() will result in a bogus datetime.
Today is *not* Saturday March 2nd, 120 ...
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1061
---
js/ui/environment.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/ui/environment.js b/js/ui/environment.js
index f3f2d17c7..a9cc16dee 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -126,7 +126,7 @@ function init() {
_localTimeZone = GLib.TimeZone.new_local();
let dt = GLib.DateTime.new(_localTimeZone,
- this.getYear(),
+ this.getFullYear(),
this.getMonth() + 1,
this.getDate(),
this.getHours(),
--
2.26.2

View File

@ -0,0 +1,152 @@
From c9277326055c96185a80b68d4228eee360bb0e7c Mon Sep 17 00:00:00 2001
From: Georges Basile Stavracas Neto <georges.stavracas@gmail.com>
Date: Thu, 1 Aug 2019 20:58:20 -0300
Subject: [PATCH 3/6] shell/app-system: Monitor for icon theme changes
Whenever an app is installed, the usual routine is
to run 'gtk-update-icon-cache' after installing all
of the app's files.
The side effect of that is that the .desktop file of
the application is installed before the icon theme
is updated. By the time GAppInfoMonitor emits the
'changed' signal, the icon theme is not yet updated,
leading to StIcon use the fallback icon.
Under some circumstances (e.g. on very slow spinning
disks) the app icon is never actually loaded, and we
see the fallback icon forever.
Monitor the icon theme for changes when an app is
installed. Try as many as 6 times before giving up
on detecting an icon theme update.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/661
---
src/shell-app-system.c | 54 +++++++++++++++++++++++++++++++++++++++
src/st/st-texture-cache.c | 8 ++++++
src/st/st-texture-cache.h | 2 ++
3 files changed, 64 insertions(+)
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index f632cbe54..127f29ef0 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -14,6 +14,14 @@
#include "shell-app-system-private.h"
#include "shell-global.h"
#include "shell-util.h"
+#include "st.h"
+
+/* Rescan for at most RESCAN_TIMEOUT_MS * MAX_RESCAN_RETRIES. That
+ * should be plenty of time for even a slow spinning drive to update
+ * the icon cache.
+ */
+#define RESCAN_TIMEOUT_MS 2500
+#define MAX_RESCAN_RETRIES 6
/* Vendor prefixes are something that can be preprended to a .desktop
* file name. Undo this.
@@ -51,6 +59,9 @@ struct _ShellAppSystemPrivate {
GHashTable *id_to_app;
GHashTable *startup_wm_class_to_id;
GList *installed_apps;
+
+ guint rescan_icons_timeout_id;
+ guint n_rescan_retries;
};
static void shell_app_system_finalize (GObject *object);
@@ -157,12 +168,54 @@ stale_app_remove_func (gpointer key,
return app_is_stale (value);
}
+static gboolean
+rescan_icon_theme_cb (gpointer user_data)
+{
+ ShellAppSystemPrivate *priv;
+ ShellAppSystem *self;
+ StTextureCache *texture_cache;
+ gboolean rescanned;
+
+ self = (ShellAppSystem *) user_data;
+ priv = self->priv;
+
+ texture_cache = st_texture_cache_get_default ();
+ rescanned = st_texture_cache_rescan_icon_theme (texture_cache);
+
+ priv->n_rescan_retries++;
+
+ if (rescanned || priv->n_rescan_retries >= MAX_RESCAN_RETRIES)
+ {
+ priv->n_rescan_retries = 0;
+ priv->rescan_icons_timeout_id = 0;
+ return G_SOURCE_REMOVE;
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+rescan_icon_theme (ShellAppSystem *self)
+{
+ ShellAppSystemPrivate *priv = self->priv;
+
+ priv->n_rescan_retries = 0;
+
+ if (priv->rescan_icons_timeout_id > 0)
+ return;
+
+ priv->rescan_icons_timeout_id = g_timeout_add (RESCAN_TIMEOUT_MS,
+ rescan_icon_theme_cb,
+ self);
+}
+
static void
installed_changed (GAppInfoMonitor *monitor,
gpointer user_data)
{
ShellAppSystem *self = user_data;
+ rescan_icon_theme (self);
scan_startup_wm_class_to_id (self);
g_hash_table_foreach_remove (self->priv->id_to_app, stale_app_remove_func, NULL);
@@ -200,6 +253,7 @@ shell_app_system_finalize (GObject *object)
g_hash_table_destroy (priv->id_to_app);
g_hash_table_destroy (priv->startup_wm_class_to_id);
g_list_free_full (priv->installed_apps, g_object_unref);
+ g_clear_handle_id (&priv->rescan_icons_timeout_id, g_source_remove);
G_OBJECT_CLASS (shell_app_system_parent_class)->finalize (object);
}
diff --git a/src/st/st-texture-cache.c b/src/st/st-texture-cache.c
index c1331747f..4d0d617c4 100644
--- a/src/st/st-texture-cache.c
+++ b/src/st/st-texture-cache.c
@@ -1554,3 +1554,11 @@ st_texture_cache_get_default (void)
instance = g_object_new (ST_TYPE_TEXTURE_CACHE, NULL);
return instance;
}
+
+gboolean
+st_texture_cache_rescan_icon_theme (StTextureCache *cache)
+{
+ StTextureCachePrivate *priv = cache->priv;
+
+ return gtk_icon_theme_rescan_if_needed (priv->icon_theme);
+}
diff --git a/src/st/st-texture-cache.h b/src/st/st-texture-cache.h
index 11d1c4e64..a99316da8 100644
--- a/src/st/st-texture-cache.h
+++ b/src/st/st-texture-cache.h
@@ -113,4 +113,6 @@ CoglTexture * st_texture_cache_load (StTextureCache *cache,
void *data,
GError **error);
+gboolean st_texture_cache_rescan_icon_theme (StTextureCache *cache);
+
#endif /* __ST_TEXTURE_CACHE_H__ */
--
2.26.2

View File

@ -0,0 +1,124 @@
From 2a4f33df723d4b9ce68e5948b568a89675d37411 Mon Sep 17 00:00:00 2001
From: Christian Hergert <chergert@redhat.com>
Date: Wed, 26 Feb 2020 14:46:20 -0800
Subject: [PATCH 4/6] 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 86a00b6872375a266449beee1ea6d5e94f1ebbcb 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
---
src/shell-global.c | 70 +++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 63 insertions(+), 7 deletions(-)
diff --git a/src/shell-global.c b/src/shell-global.c
index df84b6b0d..4b33778e0 100644
--- a/src/shell-global.c
+++ b/src/shell-global.c
@@ -1572,6 +1572,55 @@ delete_variant_cb (GObject *object,
g_hash_table_remove (global->save_ops, object);
}
+static void
+replace_contents_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = source_object;
+ GBytes *bytes = task_data;
+ GError *error = NULL;
+ const gchar *data;
+ gsize len;
+
+ data = g_bytes_get_data (bytes, &len);
+
+ if (!g_file_replace_contents (file, data, len, NULL, FALSE,
+ G_FILE_CREATE_REPLACE_DESTINATION,
+ NULL, cancellable, &error))
+ g_task_return_error (task, g_steal_pointer (&error));
+ else
+ g_task_return_boolean (task, TRUE);
+}
+
+static void
+replace_contents_async (GFile *path,
+ GBytes *bytes,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = NULL;
+
+ g_assert (G_IS_FILE (path));
+ g_assert (bytes != NULL);
+ g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+ task = g_task_new (path, cancellable, callback, user_data);
+ g_task_set_source_tag (task, replace_contents_async);
+ g_task_set_task_data (task, g_bytes_ref (bytes), (GDestroyNotify)g_bytes_unref);
+ g_task_run_in_thread (task, replace_contents_worker);
+}
+
+static gboolean
+replace_contents_finish (GFile *file,
+ GAsyncResult *result,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
static void
replace_variant_cb (GObject *object,
GAsyncResult *result,
@@ -1580,7 +1629,7 @@ replace_variant_cb (GObject *object,
ShellGlobal *global = user_data;
GError *error = NULL;
- if (!g_file_replace_contents_finish (G_FILE (object), result, NULL, &error))
+ if (!replace_contents_finish (G_FILE (object), result, &error))
{
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
{
@@ -1616,12 +1665,19 @@ save_variant (ShellGlobal *global,
}
else
{
- g_file_replace_contents_async (path,
- g_variant_get_data (variant),
- g_variant_get_size (variant),
- NULL, FALSE,
- G_FILE_CREATE_REPLACE_DESTINATION,
- cancellable, replace_variant_cb, global);
+ g_autoptr(GBytes) bytes = NULL;
+
+ bytes = g_bytes_new_with_free_func (g_variant_get_data (variant),
+ g_variant_get_size (variant),
+ (GDestroyNotify)g_variant_unref,
+ g_variant_ref (variant));
+ /* g_file_replace_contents_async() can potentially fsync() from the
+ * calling thread when completing the asynchronous task. Instead, we
+ * want to force that fsync() to a thread to avoid blocking the
+ * compository main loop. Using our own replace_contents_async()
+ * simply executes the operation synchronously from a thread.
+ */
+ replace_contents_async (path, bytes, cancellable, replace_variant_cb, global);
}
g_object_unref (path);
--
2.26.2

View File

@ -0,0 +1,674 @@
From a3fc35a2b452855d004549afbec57d1b4f36c917 Mon Sep 17 00:00:00 2001
From: Christian Hergert <chergert@redhat.com>
Date: Thu, 27 Feb 2020 19:36:14 -0800
Subject: [PATCH 5/6] app-cache: add ShellAppCache for GAppInfo caching
This caches GAppInfo so that the compositor thread does not have to perform
costly disk access to load them. Instead, they are loaded from a worker
thread and the ShellAppCache notifies of changes.
To simplify maintenance, ShellAppCache manages this directly and the
existing ShellAppSystem wraps the cache. We may want to graft these
together in the future, but now it provides the easiest way to backport
changes to older Shell releases.
Another source of compositor thread disk access was in determining the
name for an application directory. Translations are provided via GKeyFile
installed in "desktop-directories". Each time we would build the name
for a label (or update it) we would have to load all of these files.
Instead, the ShellAppCache caches that information and updates the cache
in bulk when those change. We can reduce this in the future to do less
work, but chances are these will come together anyway so that is probably
worth fixing if we ever come across it.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/2282
---
js/ui/appDisplay.js | 12 +-
src/meson.build | 5 +-
src/shell-app-cache-private.h | 19 ++
src/shell-app-cache.c | 404 ++++++++++++++++++++++++++++++++++
src/shell-app-system.c | 34 ++-
src/shell-util.c | 16 ++
src/shell-util.h | 2 +
7 files changed, 463 insertions(+), 29 deletions(-)
create mode 100644 src/shell-app-cache-private.h
create mode 100644 src/shell-app-cache.c
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index 7fad02cd0..a2d691085 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -78,15 +78,9 @@ function _getFolderName(folder) {
let name = folder.get_string('name');
if (folder.get_boolean('translate')) {
- let keyfile = new GLib.KeyFile();
- let path = 'desktop-directories/' + name;
-
- try {
- keyfile.load_from_data_dirs(path, GLib.KeyFileFlags.NONE);
- name = keyfile.get_locale_string('Desktop Entry', 'Name', null);
- } catch(e) {
- return name;
- }
+ let translated = Shell.util_get_translated_folder_name(name);
+ if (translated !== null)
+ return translated;
}
return name;
diff --git a/src/meson.build b/src/meson.build
index 97a5a796c..2b911d347 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -108,6 +108,7 @@ endif
libshell_private_headers = [
'shell-app-private.h',
+ 'shell-app-cache-private.h',
'shell-app-system-private.h',
'shell-global-private.h',
'shell-window-tracker-private.h',
@@ -146,7 +147,9 @@ if have_networkmanager
libshell_sources += 'shell-network-agent.c'
endif
-libshell_private_sources = []
+libshell_private_sources = [
+ 'shell-app-cache.c',
+]
if enable_recorder
libshell_sources += ['shell-recorder.c']
diff --git a/src/shell-app-cache-private.h b/src/shell-app-cache-private.h
new file mode 100644
index 000000000..b73094ab1
--- /dev/null
+++ b/src/shell-app-cache-private.h
@@ -0,0 +1,19 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+#ifndef __SHELL_APP_CACHE_PRIVATE_H__
+#define __SHELL_APP_CACHE_PRIVATE_H__
+
+#include <gio/gio.h>
+#include <gio/gdesktopappinfo.h>
+
+#define SHELL_TYPE_APP_CACHE (shell_app_cache_get_type())
+
+G_DECLARE_FINAL_TYPE (ShellAppCache, shell_app_cache, SHELL, APP_CACHE, GObject)
+
+ShellAppCache *shell_app_cache_get_default (void);
+GList *shell_app_cache_get_all (ShellAppCache *cache);
+GDesktopAppInfo *shell_app_cache_get_info (ShellAppCache *cache,
+ const char *id);
+char *shell_app_cache_translate_folder (ShellAppCache *cache,
+ const char *name);
+
+#endif /* __SHELL_APP_CACHE_PRIVATE_H__ */
diff --git a/src/shell-app-cache.c b/src/shell-app-cache.c
new file mode 100644
index 000000000..15d4734d0
--- /dev/null
+++ b/src/shell-app-cache.c
@@ -0,0 +1,404 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+
+#include "config.h"
+
+#include "shell-app-cache-private.h"
+
+/**
+ * SECTION:shell-app-cache
+ * @title: ShellAppCache
+ * @short_description: application information cache
+ *
+ * The #ShellAppCache is responsible for caching information about #GAppInfo
+ * to ensure that the compositor thread never needs to perform disk reads to
+ * access them. All of the work is done off-thread. When the new data has
+ * been loaded, a #ShellAppCache::changed signal is emitted.
+ *
+ * Additionally, the #ShellAppCache caches information about translations for
+ * directories. This allows translation provided in [Desktop Entry] GKeyFiles
+ * to be available when building StLabel and other elements without performing
+ * costly disk reads.
+ *
+ * Various monitors are used to keep this information up to date while the
+ * Shell is running.
+ */
+
+#define DEFAULT_TIMEOUT_SECONDS 5
+
+struct _ShellAppCache
+{
+ GObject parent_instance;
+
+ GAppInfoMonitor *monitor;
+ GPtrArray *dir_monitors;
+ GHashTable *folders;
+ GCancellable *cancellable;
+ GList *app_infos;
+
+ guint queued_update;
+};
+
+typedef struct
+{
+ GList *app_infos;
+ GHashTable *folders;
+} CacheState;
+
+G_DEFINE_TYPE (ShellAppCache, shell_app_cache, G_TYPE_OBJECT)
+
+enum {
+ CHANGED,
+ N_SIGNALS
+};
+
+static guint signals [N_SIGNALS];
+
+static void
+cache_state_free (CacheState *state)
+{
+ g_clear_pointer (&state->folders, g_hash_table_unref);
+ g_list_free_full (state->app_infos, g_object_unref);
+ g_slice_free (CacheState, state);
+}
+
+static CacheState *
+cache_state_new (void)
+{
+ CacheState *state;
+
+ state = g_slice_new0 (CacheState);
+ state->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ return g_steal_pointer (&state);
+}
+
+/**
+ * shell_app_cache_get_default:
+ *
+ * Gets the default #ShellAppCache.
+ *
+ * Returns: (transfer none): a #ShellAppCache
+ */
+ShellAppCache *
+shell_app_cache_get_default (void)
+{
+ static ShellAppCache *instance;
+
+ if (instance == NULL)
+ {
+ instance = g_object_new (SHELL_TYPE_APP_CACHE, NULL);
+ g_object_add_weak_pointer (G_OBJECT (instance), (gpointer *)&instance);
+ }
+
+ return instance;
+}
+
+static void
+load_folder (GHashTable *folders,
+ const char *path)
+{
+ g_autoptr(GDir) dir = NULL;
+ const char *name;
+
+ g_assert (folders != NULL);
+ g_assert (path != NULL);
+
+ dir = g_dir_open (path, 0, NULL);
+ if (dir == NULL)
+ return;
+
+ while ((name = g_dir_read_name (dir)))
+ {
+ g_autofree gchar *filename = NULL;
+ g_autoptr(GKeyFile) keyfile = NULL;
+
+ /* First added wins */
+ if (g_hash_table_contains (folders, name))
+ continue;
+
+ filename = g_build_filename (path, name, NULL);
+ keyfile = g_key_file_new ();
+
+ if (g_key_file_load_from_file (keyfile, filename, G_KEY_FILE_NONE, NULL))
+ {
+ gchar *translated;
+
+ translated = g_key_file_get_locale_string (keyfile,
+ "Desktop Entry", "Name",
+ NULL, NULL);
+
+ if (translated != NULL)
+ g_hash_table_insert (folders, g_strdup (name), translated);
+ }
+ }
+}
+
+static void
+load_folders (GHashTable *folders)
+{
+ const char * const *dirs;
+ g_autofree gchar *userdir = NULL;
+ guint i;
+
+ g_assert (folders != NULL);
+
+ userdir = g_build_filename (g_get_user_data_dir (), "desktop-directories", NULL);
+ load_folder (folders, userdir);
+
+ dirs = g_get_system_data_dirs ();
+ for (i = 0; dirs[i] != NULL; i++)
+ {
+ g_autofree gchar *sysdir = g_build_filename (dirs[i], "desktop-directories", NULL);
+ load_folder (folders, sysdir);
+ }
+}
+
+static void
+shell_app_cache_worker (GTask *task,
+ gpointer source_object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ CacheState *state;
+
+ g_assert (G_IS_TASK (task));
+ g_assert (SHELL_IS_APP_CACHE (source_object));
+
+ state = cache_state_new ();
+ state->app_infos = g_app_info_get_all ();
+ load_folders (state->folders);
+
+ g_task_return_pointer (task, state, (GDestroyNotify) cache_state_free);
+}
+
+static void
+apply_update_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ ShellAppCache *cache = (ShellAppCache *)object;
+ g_autoptr(GError) error = NULL;
+ CacheState *state;
+
+ g_assert (SHELL_IS_APP_CACHE (cache));
+ g_assert (G_IS_TASK (result));
+ g_assert (user_data == NULL);
+
+ state = g_task_propagate_pointer (G_TASK (result), &error);
+
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+ return;
+
+ g_list_free_full (cache->app_infos, g_object_unref);
+ cache->app_infos = g_steal_pointer (&state->app_infos);
+
+ g_clear_pointer (&cache->folders, g_hash_table_unref);
+ cache->folders = g_steal_pointer (&state->folders);
+
+ g_signal_emit (cache, signals[CHANGED], 0);
+
+ cache_state_free (state);
+}
+
+static gboolean
+shell_app_cache_do_update (gpointer user_data)
+{
+ ShellAppCache *cache = user_data;
+ g_autoptr(GTask) task = NULL;
+
+ cache->queued_update = 0;
+
+ /* Reset the cancellable state so we don't race with
+ * two updates coming back overlapped and applying the
+ * information in the wrong order.
+ */
+ g_cancellable_cancel (cache->cancellable);
+ g_clear_object (&cache->cancellable);
+ cache->cancellable = g_cancellable_new ();
+
+ task = g_task_new (cache, cache->cancellable, apply_update_cb, NULL);
+ g_task_set_source_tag (task, shell_app_cache_do_update);
+ g_task_run_in_thread (task, shell_app_cache_worker);
+
+ return G_SOURCE_REMOVE;
+}
+
+static void
+shell_app_cache_queue_update (ShellAppCache *self)
+{
+ g_assert (SHELL_IS_APP_CACHE (self));
+
+ if (self->queued_update != 0)
+ g_source_remove (self->queued_update);
+
+ self->queued_update = g_timeout_add_seconds (DEFAULT_TIMEOUT_SECONDS,
+ shell_app_cache_do_update,
+ self);
+}
+
+static void
+monitor_desktop_directories_for_data_dir (ShellAppCache *self,
+ const gchar *directory)
+{
+ g_autofree gchar *subdir = NULL;
+ g_autoptr(GFile) file = NULL;
+ g_autoptr(GFileMonitor) monitor = NULL;
+
+ g_assert (SHELL_IS_APP_CACHE (self));
+
+ if (directory == NULL)
+ return;
+
+ subdir = g_build_filename (directory, "desktop-directories", NULL);
+ file = g_file_new_for_path (subdir);
+ monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
+
+ if (monitor != NULL)
+ {
+ g_file_monitor_set_rate_limit (monitor, DEFAULT_TIMEOUT_SECONDS * 1000);
+ g_signal_connect_object (monitor,
+ "changed",
+ G_CALLBACK (shell_app_cache_queue_update),
+ self,
+ G_CONNECT_SWAPPED);
+ g_ptr_array_add (self->dir_monitors, g_steal_pointer (&monitor));
+ }
+}
+
+static void
+shell_app_cache_finalize (GObject *object)
+{
+ ShellAppCache *self = (ShellAppCache *)object;
+
+ g_clear_object (&self->monitor);
+
+ if (self->queued_update)
+ {
+ g_source_remove (self->queued_update);
+ self->queued_update = 0;
+ }
+
+ g_clear_pointer (&self->dir_monitors, g_ptr_array_unref);
+ g_clear_pointer (&self->folders, g_hash_table_unref);
+ g_list_free_full (self->app_infos, g_object_unref);
+
+ G_OBJECT_CLASS (shell_app_cache_parent_class)->finalize (object);
+}
+
+static void
+shell_app_cache_class_init (ShellAppCacheClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = shell_app_cache_finalize;
+
+ /**
+ * ShellAppCache::changed:
+ *
+ * The "changed" signal is emitted when the cache has updated
+ * information about installed applications.
+ */
+ signals [CHANGED] =
+ g_signal_new ("changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+}
+
+static void
+shell_app_cache_init (ShellAppCache *self)
+{
+ const gchar * const *sysdirs;
+ guint i;
+
+ /* Monitor directories for translation changes */
+ self->dir_monitors = g_ptr_array_new_with_free_func (g_object_unref);
+ monitor_desktop_directories_for_data_dir (self, g_get_user_data_dir ());
+ sysdirs = g_get_system_data_dirs ();
+ for (i = 0; sysdirs[i] != NULL; i++)
+ monitor_desktop_directories_for_data_dir (self, sysdirs[i]);
+
+ /* Load translated directory names immediately */
+ self->folders = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ load_folders (self->folders);
+
+ /* Setup AppMonitor to track changes */
+ self->monitor = g_app_info_monitor_get ();
+ g_signal_connect_object (self->monitor,
+ "changed",
+ G_CALLBACK (shell_app_cache_queue_update),
+ self,
+ G_CONNECT_SWAPPED);
+ self->app_infos = g_app_info_get_all ();
+}
+
+/**
+ * shell_app_cache_get_all:
+ * @cache: (nullable): a #ShellAppCache or %NULL
+ *
+ * Like g_app_info_get_all() but always returns a
+ * cached set of application info so the caller can be
+ * sure that I/O will not happen on the current thread.
+ *
+ * Returns: (transfer none) (element-type GAppInfo):
+ * a #GList of references to #GAppInfo.
+ */
+GList *
+shell_app_cache_get_all (ShellAppCache *cache)
+{
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
+
+ return cache->app_infos;
+}
+
+/**
+ * shell_app_cache_get_info:
+ * @cache: (nullable): a #ShellAppCache or %NULL
+ * @id: the application id
+ *
+ * A replacement for g_desktop_app_info_new() that will lookup the
+ * information from the cache instead of (re)loading from disk.
+ *
+ * Returns: (nullable) (transfer none): a #GDesktopAppInfo or %NULL
+ */
+GDesktopAppInfo *
+shell_app_cache_get_info (ShellAppCache *cache,
+ const char *id)
+{
+ const GList *iter;
+
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
+
+ for (iter = cache->app_infos; iter != NULL; iter = iter->next)
+ {
+ GAppInfo *info = iter->data;
+
+ if (g_strcmp0 (id, g_app_info_get_id (info)) == 0)
+ return G_DESKTOP_APP_INFO (info);
+ }
+
+ return NULL;
+}
+
+/**
+ * shell_app_cache_translate_folder:
+ * @cache: (nullable): a #ShellAppCache or %NULL
+ * @name: the folder name
+ *
+ * Gets the translated folder name for @name if any exists.
+ *
+ * Returns: (nullable): the translated string or %NULL if there is no
+ * translation.
+ */
+char *
+shell_app_cache_translate_folder (ShellAppCache *cache,
+ const char *name)
+{
+ g_return_val_if_fail (SHELL_IS_APP_CACHE (cache), NULL);
+
+ if (name == NULL)
+ return NULL;
+
+ return g_strdup (g_hash_table_lookup (cache->folders, name));
+}
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index 127f29ef0..828fa726a 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -9,6 +9,7 @@
#include <gio/gio.h>
#include <glib/gi18n.h>
+#include "shell-app-cache-private.h"
#include "shell-app-private.h"
#include "shell-window-tracker-private.h"
#include "shell-app-system-private.h"
@@ -94,14 +95,14 @@ static void
scan_startup_wm_class_to_id (ShellAppSystem *self)
{
ShellAppSystemPrivate *priv = self->priv;
- GList *l;
+ const GList *l;
+ GList *all;
g_hash_table_remove_all (priv->startup_wm_class_to_id);
- g_list_free_full (priv->installed_apps, g_object_unref);
- priv->installed_apps = g_app_info_get_all ();
+ all = shell_app_cache_get_all (shell_app_cache_get_default ());
- for (l = priv->installed_apps; l != NULL; l = l->next)
+ for (l = all; l != NULL; l = l->next)
{
GAppInfo *info = l->data;
const char *startup_wm_class, *id, *old_id;
@@ -131,7 +132,8 @@ app_is_stale (ShellApp *app)
if (shell_app_is_window_backed (app))
return FALSE;
- info = g_desktop_app_info_new (shell_app_get_id (app));
+ info = shell_app_cache_get_info (shell_app_cache_get_default (),
+ shell_app_get_id (app));
if (!info)
return TRUE;
@@ -156,7 +158,6 @@ app_is_stale (ShellApp *app)
g_icon_equal (g_app_info_get_icon (old_info),
g_app_info_get_icon (new_info));
- g_object_unref (info);
return !is_unchanged;
}
@@ -210,11 +211,9 @@ rescan_icon_theme (ShellAppSystem *self)
}
static void
-installed_changed (GAppInfoMonitor *monitor,
- gpointer user_data)
+installed_changed (ShellAppCache *cache,
+ ShellAppSystem *self)
{
- ShellAppSystem *self = user_data;
-
rescan_icon_theme (self);
scan_startup_wm_class_to_id (self);
@@ -227,7 +226,7 @@ static void
shell_app_system_init (ShellAppSystem *self)
{
ShellAppSystemPrivate *priv;
- GAppInfoMonitor *monitor;
+ ShellAppCache *cache;
self->priv = priv = shell_app_system_get_instance_private (self);
@@ -238,9 +237,9 @@ shell_app_system_init (ShellAppSystem *self)
priv->startup_wm_class_to_id = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
- monitor = g_app_info_monitor_get ();
- g_signal_connect (monitor, "changed", G_CALLBACK (installed_changed), self);
- installed_changed (monitor, self);
+ cache = shell_app_cache_get_default ();
+ g_signal_connect (cache, "changed", G_CALLBACK (installed_changed), self);
+ installed_changed (cache, self);
}
static void
@@ -293,13 +292,12 @@ shell_app_system_lookup_app (ShellAppSystem *self,
if (app)
return app;
- info = g_desktop_app_info_new (id);
+ info = shell_app_cache_get_info (shell_app_cache_get_default (), id);
if (!info)
return NULL;
app = _shell_app_new (info);
g_hash_table_insert (priv->id_to_app, (char *) shell_app_get_id (app), app);
- g_object_unref (info);
return app;
}
@@ -506,7 +504,5 @@ shell_app_system_search (const char *search_string)
GList *
shell_app_system_get_installed (ShellAppSystem *self)
{
- ShellAppSystemPrivate *priv = self->priv;
-
- return priv->installed_apps;
+ return shell_app_cache_get_all (shell_app_cache_get_default ());
}
diff --git a/src/shell-util.c b/src/shell-util.c
index fa3fc08c8..370784523 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -16,6 +16,7 @@
#include <GL/gl.h>
#include <cogl/cogl.h>
+#include "shell-app-cache-private.h"
#include "shell-util.h"
#include <glib/gi18n-lib.h>
#include <gtk/gtk.h>
@@ -639,3 +640,18 @@ shell_util_has_x11_display_extension (MetaDisplay *display,
xdisplay = meta_x11_display_get_xdisplay (x11_display);
return XQueryExtension (xdisplay, extension, &op, &event, &error);
}
+
+/**
+ * shell_util_get_translated_folder_name:
+ * @name: the untranslated folder name
+ *
+ * Attempts to translate the folder @name using translations provided
+ * by .directory files.
+ *
+ * Returns: (nullable): a translated string or %NULL
+ */
+char *
+shell_util_get_translated_folder_name (const char *name)
+{
+ return shell_app_cache_translate_folder (shell_app_cache_get_default (), name);
+}
diff --git a/src/shell-util.h b/src/shell-util.h
index 02b8404e9..843a1253d 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -62,6 +62,8 @@ void shell_util_check_cloexec_fds (void);
gboolean shell_util_has_x11_display_extension (MetaDisplay *display,
const char *extension);
+char *shell_util_get_translated_folder_name (const char *name);
+
G_END_DECLS
#endif /* __SHELL_UTIL_H__ */
--
2.26.2

View File

@ -0,0 +1,66 @@
From a0df79f8de4c13c36ed3b22cfdbb78e324424ef1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Sat, 14 Mar 2020 14:45:42 +0100
Subject: [PATCH 6/6] js: Always use AppSystem to lookup apps
There is no good reason for bypassing the application cache in
AppSystem and loading .desktop files again.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1093
---
js/ui/appDisplay.js | 4 ++--
js/ui/calendar.js | 16 ++++++++++------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/js/ui/appDisplay.js b/js/ui/appDisplay.js
index a2d691085..cb2be7d3c 100644
--- a/js/ui/appDisplay.js
+++ b/js/ui/appDisplay.js
@@ -1001,8 +1001,8 @@ var AppSearchProvider = class AppSearchProvider {
let results = [];
groups.forEach(group => {
group = group.filter(appID => {
- let app = Gio.DesktopAppInfo.new(appID);
- return app && app.should_show();
+ const app = this._appSys.lookup_app(appID);
+ return app && app.app_info.should_show();
});
results = results.concat(group.sort(
(a, b) => usage.compare(a, b)
diff --git a/js/ui/calendar.js b/js/ui/calendar.js
index cd3e879c4..3ae2e44f8 100644
--- a/js/ui/calendar.js
+++ b/js/ui/calendar.js
@@ -791,8 +791,9 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
this._title.connect('clicked', this._onTitleClicked.bind(this));
this._title.connect('key-focus-in', this._onKeyFocusIn.bind(this));
- Shell.AppSystem.get_default().connect('installed-changed',
- this._appInstalledChanged.bind(this));
+ this._appSys = Shell.AppSystem.get_default();
+ this._appSys.connect('installed-changed',
+ this._appInstalledChanged.bind(this));
this._appInstalledChanged();
}
@@ -883,10 +884,13 @@ var EventsSection = class EventsSection extends MessageList.MessageListSection {
Main.overview.hide();
Main.panel.closeCalendar();
- let app = this._getCalendarApp();
- if (app.get_id() == 'evolution.desktop')
- app = Gio.DesktopAppInfo.new('evolution-calendar.desktop');
- app.launch([], global.create_app_launch_context(0, -1));
+ let appInfo = this._getCalendarApp();
+ if (app.get_id() == 'evolution.desktop') {
+ let app = this._appSys.lookup_app('evolution-calendar.desktop');
+ if (app)
+ appInfo = app.app_info;
+ }
+ appInfo.launch([], global.create_app_launch_context(0, -1));
}
setDate(date) {
--
2.26.2

View File

@ -1,4 +1,4 @@
From de891fadb0b40a9b6e84131b82086e42d86992a1 Mon Sep 17 00:00:00 2001
From 3252f05b8745a5d3118986474793fe3ecc2b041c Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 19 Apr 2016 13:12:46 -0400
Subject: [PATCH] loginDialog: allow timed login with disabled user list
@ -13,8 +13,8 @@ auth prompt, in that scenario.
---
data/theme/gnome-shell-sass/_common.scss | 4 +++
js/gdm/authPrompt.js | 41 +++++++++++++++++++++++-
js/gdm/loginDialog.js | 23 ++++++++++++-
3 files changed, 66 insertions(+), 2 deletions(-)
js/gdm/loginDialog.js | 25 +++++++++++++--
3 files changed, 67 insertions(+), 3 deletions(-)
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index a6357baad..c2df28279 100644
@ -97,7 +97,7 @@ index 27eb31a89..cf77b3f26 100644
if (this._preemptiveAnswerWatchId) {
this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId);
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index 6c4d1357d..9aaa013d8 100644
index 6c4d1357d..b4df6e959 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -734,6 +734,9 @@ var LoginDialog = GObject.registerClass({
@ -110,7 +110,7 @@ index 6c4d1357d..9aaa013d8 100644
}
}
@@ -1020,9 +1023,21 @@ var LoginDialog = GObject.registerClass({
@@ -1020,16 +1023,31 @@ var LoginDialog = GObject.registerClass({
let loginItem = null;
let animationTime;
@ -125,15 +125,16 @@ index 6c4d1357d..9aaa013d8 100644
+ },
() => {
- loginItem = this._userList.getItemFromUserName(userName);
+ this._timedLoginUserListHold = null;
+
+ if (this._disableUserList)
+ return;
+
loginItem = this._userList.getItemFromUserName(userName);
+ loginItem = this._disableUserList
+ ? this._authPrompt
+ : this._userList.getItemFromUserName(userName);
// If there is an animation running on the item, reset it.
@@ -1030,6 +1045,9 @@ var LoginDialog = GObject.registerClass({
loginItem.hideTimedLoginIndicator();
},
() => {
@ -154,5 +155,5 @@ index 6c4d1357d..9aaa013d8 100644
if (delay > _TIMED_LOGIN_IDLE_THRESHOLD &&
this._authPrompt.actor.visible)
--
2.21.0
2.26.2

View File

@ -0,0 +1,643 @@
From 781dfcf6ce7168c6b116d58df5f1c67291a7b513 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 16 May 2019 00:57:27 +0200
Subject: [PATCH 01/11] introspect: Include `sandboxed-app-id` as well
App IDs in gnome-shell don't match AppStream, Flatpak or Snap IDs. For the
desktop portal, the latter two are more relevant, so include it in the
returned information.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/1289
---
js/misc/introspect.js | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index f7a7f2fe6..1e8300d0a 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -55,6 +55,11 @@ var IntrospectService = class {
return APP_WHITELIST.includes(sender);
}
+ _getSandboxedAppId(app) {
+ let ids = app.get_windows().map(w => w.get_sandboxed_app_id());
+ return ids.find(id => id != null);
+ }
+
_syncRunningApplications() {
let tracker = Shell.WindowTracker.get_default();
let apps = this._appSystem.get_running();
@@ -76,6 +81,10 @@ var IntrospectService = class {
newActiveApplication = app.get_id();
}
+ let sandboxedAppId = this._getSandboxedAppId(app);
+ if (sandboxedAppId)
+ appInfo['sandboxed-app-id'] = new GLib.Variant('s', sandboxedAppId);
+
newRunningApplications[app.get_id()] = appInfo;
}
@@ -137,6 +146,7 @@ var IntrospectService = class {
let frameRect = window.get_frame_rect();
let title = window.get_title();
let wmClass = window.get_wm_class();
+ let sandboxedAppId = window.get_sandboxed_app_id();
windowsList[windowId] = {
'app-id': GLib.Variant.new('s', app.get_id()),
@@ -153,6 +163,10 @@ var IntrospectService = class {
if (wmClass != null)
windowsList[windowId]['wm-class'] = GLib.Variant.new('s', wmClass);
+
+ if (sandboxedAppId != null)
+ windowsList[windowId]['sandboxed-app-id'] =
+ GLib.Variant.new('s', sandboxedAppId);
}
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
--
2.26.2
From b0b4fb82c058722e2171d24902ba3855ffe243f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 18 Sep 2019 14:57:48 +0200
Subject: [PATCH 02/11] 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
---
js/misc/introspect.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 1e8300d0a..cee6409a8 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -128,7 +128,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');
--
2.26.2
From 23556e03db3743ddf478a3c1bbb64946c687afdf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 25 Nov 2019 19:44:10 +0100
Subject: [PATCH 03/11] 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
---
js/misc/introspect.js | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index cee6409a8..f14eabfad 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -39,6 +39,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) {
@@ -52,7 +61,7 @@ var IntrospectService = class {
}
_isSenderWhitelisted(sender) {
- return APP_WHITELIST.includes(sender);
+ return [...this._whitelistMap.values()].includes(sender);
}
_getSandboxedAppId(app) {
--
2.26.2
From 1a6275add6d214df958ed8a06c097445bef021bc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 25 Sep 2019 20:36:28 +0200
Subject: [PATCH 04/11] introspect: Add helper to check method call permission
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
js/misc/introspect.js | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index f14eabfad..6186754cd 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -120,9 +120,18 @@ var IntrospectService = class {
type == Meta.WindowType.UTILITY);
}
+ _isInvocationAllowed(invocation) {
+ if (this._isIntrospectEnabled())
+ return true;
+
+ if (this._isSenderWhitelisted(invocation.get_sender()))
+ return true;
+
+ return false;
+ }
+
GetRunningApplicationsAsync(params, invocation) {
- if (!this._isIntrospectEnabled() &&
- !this._isSenderWhitelisted(invocation.get_sender())) {
+ if (!this._isInvocationAllowed(invocation)) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');
@@ -137,8 +146,7 @@ var IntrospectService = class {
let apps = this._appSystem.get_running();
let windowsList = {};
- if (!this._isIntrospectEnabled() &&
- !this._isSenderWhitelisted(invocation.get_sender())) {
+ if (!this._isInvocationAllowed(invocation)) {
invocation.return_error_literal(Gio.DBusError,
Gio.DBusError.ACCESS_DENIED,
'App introspection not allowed');
--
2.26.2
From f578dc01cf774faa4504a4d258cc0e82060d988b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 11:55:33 +0200
Subject: [PATCH 05/11] shell-util: Add API to check for X11 extensions
Will be used to disable animations when running inside Xvnc. This was
done in gsd-xsettings before.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
src/shell-util.c | 26 ++++++++++++++++++++++++++
src/shell-util.h | 3 +++
2 files changed, 29 insertions(+)
diff --git a/src/shell-util.c b/src/shell-util.c
index 31bb18e70..fa3fc08c8 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -21,6 +21,8 @@
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <meta/meta-shaped-texture.h>
+#include <meta/display.h>
+#include <meta/meta-x11-display.h>
#include <locale.h>
#ifdef HAVE__NL_TIME_FIRST_WEEKDAY
@@ -613,3 +615,27 @@ shell_util_check_cloexec_fds (void)
fdwalk (check_cloexec, NULL);
g_info ("Open fd CLOEXEC check complete");
}
+
+/**
+ * shell_util_has_x11_display_extension:
+ * @display: A #MetaDisplay
+ * @extension: An X11 extension
+ *
+ * If the corresponding X11 display provides the passed extension, return %TRUE,
+ * otherwise %FALSE. If there is no X11 display, %FALSE is passed.
+ */
+gboolean
+shell_util_has_x11_display_extension (MetaDisplay *display,
+ const char *extension)
+{
+ MetaX11Display *x11_display;
+ Display *xdisplay;
+ int op, event, error;
+
+ x11_display = meta_display_get_x11_display (display);
+ if (!x11_display)
+ return FALSE;
+
+ xdisplay = meta_x11_display_get_xdisplay (x11_display);
+ return XQueryExtension (xdisplay, extension, &op, &event, &error);
+}
diff --git a/src/shell-util.h b/src/shell-util.h
index 6904f43bc..02b8404e9 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -59,6 +59,9 @@ cairo_surface_t * shell_util_composite_capture_images (ClutterCapture *captures
void shell_util_check_cloexec_fds (void);
+gboolean shell_util_has_x11_display_extension (MetaDisplay *display,
+ const char *extension);
+
G_END_DECLS
#endif /* __SHELL_UTIL_H__ */
--
2.26.2
From 48ee79bb7b48c7e93e77e35629f21bbdbabc253f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 11:56:34 +0200
Subject: [PATCH 06/11] st/settings: Add API to inhibit animations
There may be situations where we shouldn't enable animations. Make it
possible for the Shell to decide when there are such situations and in
when needed inhibit animations.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
src/st/st-settings.c | 38 +++++++++++++++++++++++++++++++++++++-
src/st/st-settings.h | 4 ++++
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/src/st/st-settings.c b/src/st/st-settings.c
index 17f2c466e..ebfd28480 100644
--- a/src/st/st-settings.c
+++ b/src/st/st-settings.c
@@ -54,6 +54,7 @@ struct _StSettings
gchar *gtk_theme;
gchar *gtk_icon_theme;
+ int inhibit_animations_count;
gboolean enable_animations;
gboolean primary_paste;
gboolean magnifier_active;
@@ -62,6 +63,41 @@ struct _StSettings
G_DEFINE_TYPE (StSettings, st_settings, G_TYPE_OBJECT)
+static gboolean
+get_enable_animations (StSettings *settings)
+{
+ if (settings->inhibit_animations_count > 0)
+ return FALSE;
+ else
+ return settings->enable_animations;
+}
+
+void
+st_settings_inhibit_animations (StSettings *settings)
+{
+ gboolean enable_animations;
+
+ enable_animations = get_enable_animations (settings);
+ settings->inhibit_animations_count++;
+
+ if (enable_animations != get_enable_animations (settings))
+ g_object_notify_by_pspec (G_OBJECT (settings),
+ props[PROP_ENABLE_ANIMATIONS]);
+}
+
+void
+st_settings_uninhibit_animations (StSettings *settings)
+{
+ gboolean enable_animations;
+
+ enable_animations = get_enable_animations (settings);
+ settings->inhibit_animations_count--;
+
+ if (enable_animations != get_enable_animations (settings))
+ g_object_notify_by_pspec (G_OBJECT (settings),
+ props[PROP_ENABLE_ANIMATIONS]);
+}
+
static void
st_settings_finalize (GObject *object)
{
@@ -95,7 +131,7 @@ st_settings_get_property (GObject *object,
switch (prop_id)
{
case PROP_ENABLE_ANIMATIONS:
- g_value_set_boolean (value, settings->enable_animations);
+ g_value_set_boolean (value, get_enable_animations (settings));
break;
case PROP_PRIMARY_PASTE:
g_value_set_boolean (value, settings->primary_paste);
diff --git a/src/st/st-settings.h b/src/st/st-settings.h
index c2c4fa23e..8b2549469 100644
--- a/src/st/st-settings.h
+++ b/src/st/st-settings.h
@@ -33,6 +33,10 @@ G_DECLARE_FINAL_TYPE (StSettings, st_settings, ST, SETTINGS, GObject)
StSettings * st_settings_get (void);
+void st_settings_inhibit_animations (StSettings *settings);
+
+void st_settings_uninhibit_animations (StSettings *settings);
+
G_END_DECLS
#endif /* __ST_SETTINGS_H__ */
--
2.26.2
From 80025388c44296b629c8f24ea673d77ffc4efc67 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 12:02:31 +0200
Subject: [PATCH 07/11] main: Inhibit animations when software rendered
This was previously decided by gsd-xsettings.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
js/ui/main.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/js/ui/main.js b/js/ui/main.js
index 978f83c3f..c3230ff03 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -147,6 +147,8 @@ function _initializeUI() {
_loadOskLayouts();
_loadDefaultStylesheet();
+ new AnimationsSettings();
+
// Setup the stage hierarchy early
layoutManager = new Layout.LayoutManager();
@@ -723,3 +725,13 @@ function showRestartMessage(message) {
let restartMessage = new RestartMessage(message);
restartMessage.open();
}
+
+var AnimationsSettings = class {
+ constructor() {
+ let backend = Meta.get_backend();
+ if (!backend.is_rendering_hardware_accelerated()) {
+ St.Settings.get().inhibit_animations();
+ return;
+ }
+ }
+};
--
2.26.2
From 788ecb60e35d8a369f0747813f37e8b1ca27cb87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 12:03:52 +0200
Subject: [PATCH 08/11] main: Inhibit animations if X server advertises
VNC-EXTENSION
This was previously done by gsd-xsettings to disable animations when
running in Xvnc.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
js/ui/main.js | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/js/ui/main.js b/js/ui/main.js
index c3230ff03..ae7c3ffd0 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -733,5 +733,12 @@ var AnimationsSettings = class {
St.Settings.get().inhibit_animations();
return;
}
+
+ let isXvnc = Shell.util_has_x11_display_extension(
+ global.display, 'VNC-EXTENSION');
+ if (isXvnc) {
+ St.Settings.get().inhibit_animations();
+ return;
+ }
}
};
--
2.26.2
From 1da5a7ce4cf0b95b96dd50b62ac6c1380fd88cb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 12:04:52 +0200
Subject: [PATCH 09/11] main: Inhibit animations when there is a remote desktop
session
If a remote desktop session asks for animations to be disabled, inhibit
animations while the session is active.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
js/ui/main.js | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
diff --git a/js/ui/main.js b/js/ui/main.js
index ae7c3ffd0..1203b3c39 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -740,5 +740,31 @@ var AnimationsSettings = class {
St.Settings.get().inhibit_animations();
return;
}
+
+ let remoteAccessController = backend.get_remote_access_controller();
+ if (!remoteAccessController)
+ return;
+
+ this._handles = new Set();
+ remoteAccessController.connect('new-handle',
+ (_, handle) => this._onNewRemoteAccessHandle(handle));
+ }
+
+ _onRemoteAccessHandleStopped(handle) {
+ let settings = St.Settings.get();
+
+ settings.uninhibit_animations();
+ this._handles.delete(handle);
+ }
+
+ _onNewRemoteAccessHandle(handle) {
+ if (!handle.get_disable_animations())
+ return;
+
+ let settings = St.Settings.get();
+
+ settings.inhibit_animations();
+ this._handles.add(handle);
+ handle.connect('stopped', this._onRemoteAccessHandleStopped.bind(this));
}
};
--
2.26.2
From ebfd46341a2d7a6338386e4be4a2807a6bc6e63c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 12:06:13 +0200
Subject: [PATCH 10/11] introspect: Rename variable
It was too generic, and would conflict with a StSettings variable.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
js/misc/introspect.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 6186754cd..8e68a7e4f 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -29,7 +29,9 @@ var IntrospectService = class {
this._syncRunningApplications();
});
- this._settings = new Gio.Settings({ schema_id: INTROSPECT_SCHEMA });
+ this._introspectSettings = new Gio.Settings({
+ schema_id: INTROSPECT_SCHEMA,
+ });
let tracker = Shell.WindowTracker.get_default();
tracker.connect('notify::focus-app',
@@ -57,7 +59,7 @@ var IntrospectService = class {
}
_isIntrospectEnabled() {
- return this._settings.get_boolean(INTROSPECT_KEY);
+ return this._introspectSettings.get_boolean(INTROSPECT_KEY);
}
_isSenderWhitelisted(sender) {
--
2.26.2
From 343e7792fc84c296b331c3fcb142ed79d2ce9bd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Tue, 1 Oct 2019 12:07:03 +0200
Subject: [PATCH 11/11] introspect: Add AnimationsEnabled property
While the gsetting is available for all who needs it, the Shell might
override it given various hueristics. Expose the decision made by the
Shell via a new property.
Intended to be used by gsd-xsettings as well as xdg-desktop-portal-gtk.
This also add a version property to the API, so that semi external
services (xdg-desktop-portal-gtk) can detect what API is expected to be
present.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/757
---
.../org.gnome.Shell.Introspect.xml | 14 ++++++++++
js/misc/introspect.js | 27 ++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
index 9508681af..d71f2414b 100644
--- a/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
+++ b/data/dbus-interfaces/org.gnome.Shell.Introspect.xml
@@ -57,5 +57,19 @@
<method name="GetWindows">
<arg name="windows" direction="out" type="a{ta{sv}}" />
</method>
+
+ <!--
+ AnimationsEnabled:
+ @short_description: Whether the shell animations are enabled
+
+ By default determined by the org.gnome.desktop.interface enable-animations
+ gsetting, but may be overridden, e.g. if there is an active screen cast or
+ remote desktop session that asked for animations to be disabled.
+
+ Since: 2
+ -->
+ <property name="AnimationsEnabled" type="b" access="read"/>
+
+ <property name="version" type="u" access="read"/>
</interface>
</node>
diff --git a/js/misc/introspect.js b/js/misc/introspect.js
index 8e68a7e4f..7c62113e5 100644
--- a/js/misc/introspect.js
+++ b/js/misc/introspect.js
@@ -1,9 +1,11 @@
-const { Gio, GLib, Meta, Shell } = imports.gi;
+const { Gio, GLib, Meta, Shell, St } = imports.gi;
const INTROSPECT_SCHEMA = 'org.gnome.shell';
const INTROSPECT_KEY = 'introspect';
const APP_WHITELIST = ['org.freedesktop.impl.portal.desktop.gtk'];
+const INTROSPECT_DBUS_API_VERSION = 2;
+
const { loadInterfaceXML } = imports.misc.fileUtils;
const IntrospectDBusIface = loadInterfaceXML('org.gnome.Shell.Introspect');
@@ -21,6 +23,7 @@ var IntrospectService = class {
this._runningApplicationsDirty = true;
this._activeApplication = null;
this._activeApplicationDirty = true;
+ this._animationsEnabled = true;
this._appSystem = Shell.AppSystem.get_default();
this._appSystem.connect('app-state-changed',
@@ -50,6 +53,11 @@ var IntrospectService = class {
(conn, name, owner) => this._whitelistMap.set(name, owner),
(conn, name) => this._whitelistMap.delete(name));
});
+
+ this._settings = St.Settings.get();
+ this._settings.connect('notify::enable-animations',
+ this._syncAnimationsEnabled.bind(this));
+ this._syncAnimationsEnabled();
}
_isStandaloneApp(app) {
@@ -191,4 +199,21 @@ var IntrospectService = class {
}
invocation.return_value(new GLib.Variant('(a{ta{sv}})', [windowsList]));
}
+
+ _syncAnimationsEnabled() {
+ let wasAnimationsEnabled = this._animationsEnabled;
+ this._animationsEnabled = this._settings.enable_animations;
+ if (wasAnimationsEnabled !== this._animationsEnabled) {
+ let variant = new GLib.Variant('b', this._animationsEnabled);
+ this._dbusImpl.emit_property_changed('AnimationsEnabled', variant);
+ }
+ }
+
+ get AnimationsEnabled() {
+ return this._animationsEnabled;
+ }
+
+ get version() {
+ return INTROSPECT_DBUS_API_VERSION;
+ }
};
--
2.26.2

View File

@ -0,0 +1,176 @@
From 4926a9b8f958617d67d603622b1382c17fe4037c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 20 May 2020 12:05:04 +0200
Subject: [PATCH 1/2] workspacesView: Avoid setting invalid geometries on views
The fullGeometry and the actualGeometry of the WorkspacesDisplay are set
from the allocation of the overviews ControlsManager and the
WorkspacesDisplay, that means they're only valid after those actors got
their allocations during Clutters allocation cycle.
Since WorkspacesDisplay._updateWorkspacesViews() is already called while
showing/mapping the WorkspacesDisplay, that allocation cycle didn't
happen yet and we end up either setting the geometries of the views to
null (in case of the fullGeometry) or to something wrong (a 0-sized
allocation in case of the actualGeometry).
So avoid setting invalid geometries on the views by initializing both
the fullGeometry and the actualGeometry to null, and then only updating
the geometries of the views after they're set to a correct value.
Note that this means we won't correctly animate the overview the first
time we open it since the animation depends on the geometries being set,
but is being started from show(), which means no allocations have
happened yet. In practice this introduces no regression though since
before this change we simply used incorrect geometries (see the 0-sized
allocation mentioned above) on the initial opening and the animation
didn't work either.
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1119
---
js/ui/workspacesView.js | 28 +++++++++++++++++-----------
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index e302296a6..02baddc6e 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -521,6 +521,7 @@ var WorkspacesDisplay = class {
this._scrollEventId = 0;
this._keyPressEventId = 0;
+ this._actualGeometry = null;
this._fullGeometry = null;
}
@@ -675,8 +676,10 @@ var WorkspacesDisplay = class {
this._workspacesViews.forEach(v => v.actor.show());
- this._updateWorkspacesFullGeometry();
- this._updateWorkspacesActualGeometry();
+ if (this._fullGeometry)
+ this._syncWorkspacesFullGeometry();
+ if (this._actualGeometry)
+ this._syncWorkspacesActualGeometry();
}
_scrollValueChanged() {
@@ -739,10 +742,10 @@ var WorkspacesDisplay = class {
// the sliding controls were never slid in at all.
setWorkspacesFullGeometry(geom) {
this._fullGeometry = geom;
- this._updateWorkspacesFullGeometry();
+ this._syncWorkspacesFullGeometry();
}
- _updateWorkspacesFullGeometry() {
+ _syncWorkspacesFullGeometry() {
if (!this._workspacesViews.length)
return;
@@ -754,18 +757,21 @@ var WorkspacesDisplay = class {
}
_updateWorkspacesActualGeometry() {
+ const [x, y] = this.actor.get_transformed_position();
+ const width = this.actor.allocation.get_width();
+ const height = this.actor.allocation.get_height();
+
+ this._actualGeometry = { x, y, width, height };
+ this._syncWorkspacesActualGeometry();
+ }
+
+ _syncWorkspacesActualGeometry() {
if (!this._workspacesViews.length)
return;
- let [x, y] = this.actor.get_transformed_position();
- let allocation = this.actor.allocation;
- let width = allocation.x2 - allocation.x1;
- let height = allocation.y2 - allocation.y1;
- let primaryGeometry = { x: x, y: y, width: width, height: height };
-
let monitors = Main.layoutManager.monitors;
for (let i = 0; i < monitors.length; i++) {
- let geometry = (i == this._primaryIndex) ? primaryGeometry : monitors[i];
+ let geometry = i === this._primaryIndex ? this._actualGeometry : monitors[i];
this._workspacesViews[i].setActualGeometry(geometry);
}
}
--
2.26.2
From 4671eebccf4e6afce8c0a869d63095b39aa7e163 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 20 May 2020 13:39:11 +0200
Subject: [PATCH 2/2] workspacesView: Only animate on show() when geometries
are already set
Animating the window clones of the overview requires the fullGeometry
and the actualGeometry to be set, which they won't be when showing the
overview for the first time. So don't even try to animate the window
clones in that case because the geometries will still be null and
accessing them in workspace.js will throw errors.
The workspace views will still get the correct layout as soon as the
allocations happen because syncing the geometries will trigger updating
the window positions. Since animations are disabled for position changes
when syncing the geometry though, we won't get an animation and the
clones will jump into place. That's not a regression though since before
this change we also didn't animate in that case because the geometries
used were simply wrong (the actualGeometry was 0-sized as explained in
the last commit).
If we wanted to fix the initial animation of the overview, we'd have to
always enable animations of the window clones when syncing geometries,
but that would break the animation of the workspace when hovering the
workspaceThumbnail slider, because right now those animations are "glued
together" using the actualGeometry, so they would get out of sync.
The reason there are no errors happening in workspace.js with the
existing code is that due to a bug in Clutter the fullGeometry of
WorkspacesDisplay gets set very early while mapping the WorkspacesViews
(because the overviews ControlsManager gets an allocation during the
resource scale calculation of a ClutterClone, see
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1181), so it
won't be set to null anymore when calling
WorkspacesView.animateToOverview().
https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1119
---
js/ui/workspacesView.js | 17 ++++++++++-------
1 file changed, 10 insertions(+), 7 deletions(-)
diff --git a/js/ui/workspacesView.js b/js/ui/workspacesView.js
index 02baddc6e..3e9d77655 100644
--- a/js/ui/workspacesView.js
+++ b/js/ui/workspacesView.js
@@ -589,13 +589,16 @@ var WorkspacesDisplay = class {
show(fadeOnPrimary) {
this._updateWorkspacesViews();
- for (let i = 0; i < this._workspacesViews.length; i++) {
- let animationType;
- if (fadeOnPrimary && i == this._primaryIndex)
- animationType = AnimationType.FADE;
- else
- animationType = AnimationType.ZOOM;
- this._workspacesViews[i].animateToOverview(animationType);
+
+ if (this._actualGeometry && this._fullGeometry) {
+ for (let i = 0; i < this._workspacesViews.length; i++) {
+ let animationType;
+ if (fadeOnPrimary && i == this._primaryIndex)
+ animationType = AnimationType.FADE;
+ else
+ animationType = AnimationType.ZOOM;
+ this._workspacesViews[i].animateToOverview(animationType);
+ }
}
this._restackedNotifyId =
--
2.26.2

View File

@ -1,7 +1,7 @@
From 3c4c37e4d0668d748ee792f7580defdf4780624a Mon Sep 17 00:00:00 2001
From 119ec213b8f9a9e55ca340dbde10b0d19becab41 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 5 Dec 2019 14:12:47 +0100
Subject: [PATCH 1/2] perf-helper: Add content for custom drawing
Subject: [PATCH 1/4] perf-helper: Add content for custom drawing
Drawing windows got a lot more involved with the advent of client-side
decorations. Instead of accounting for visible and invisible borders,
@ -14,10 +14,10 @@ https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/887
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/src/shell-perf-helper.c b/src/shell-perf-helper.c
index f115dcbdc..ba1754e02 100644
index e5eab208b..55bdbef02 100644
--- a/src/shell-perf-helper.c
+++ b/src/shell-perf-helper.c
@@ -119,9 +119,9 @@ on_window_map_event (GtkWidget *window,
@@ -120,9 +120,9 @@ on_window_map_event (GtkWidget *window,
}
static gboolean
@ -30,7 +30,7 @@ index f115dcbdc..ba1754e02 100644
{
cairo_rectangle_int_t allocation;
double x_offset, y_offset;
@@ -203,6 +203,7 @@ create_window (int width,
@@ -204,6 +204,7 @@ create_window (int width,
gboolean redraws)
{
WindowInfo *info;
@ -38,7 +38,7 @@ index f115dcbdc..ba1754e02 100644
info = g_new0 (WindowInfo, 1);
info->width = width;
@@ -218,10 +219,13 @@ create_window (int width,
@@ -219,10 +220,13 @@ create_window (int width,
info->pending = TRUE;
info->start_time = -1;
@ -54,13 +54,13 @@ index f115dcbdc..ba1754e02 100644
if (info->redraws)
--
2.23.0
2.26.2
From 0185c288c3e6b82b76f2a0704aab0e2ab20b75b8 Mon Sep 17 00:00:00 2001
From bb4c2acaef4d8fdea50915030c221e1190f704a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 5 Dec 2019 13:29:38 +0100
Subject: [PATCH 2/2] perf-helper: Remove unused atoms
Subject: [PATCH 2/4] perf-helper: Remove unused atoms
Those aren't used for anything, but make the helper dependent on X11.
@ -70,7 +70,7 @@ https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/887
1 file changed, 18 deletions(-)
diff --git a/src/shell-perf-helper.c b/src/shell-perf-helper.c
index ba1754e02..a50376e2e 100644
index 55bdbef02..d3280de96 100644
--- a/src/shell-perf-helper.c
+++ b/src/shell-perf-helper.c
@@ -12,7 +12,6 @@
@ -94,7 +94,7 @@ index ba1754e02..a50376e2e 100644
static guint timeout_id;
static GList *our_windows;
static GList *wait_windows_invocations;
@@ -350,8 +343,6 @@ on_name_lost (GDBusConnection *connection,
@@ -351,8 +344,6 @@ on_name_lost (GDBusConnection *connection,
int
main (int argc, char **argv)
{
@ -103,7 +103,7 @@ index ba1754e02..a50376e2e 100644
GOptionContext *context;
GError *error = NULL;
@@ -367,15 +358,6 @@ main (int argc, char **argv)
@@ -368,15 +359,6 @@ main (int argc, char **argv)
return 1;
}
@ -120,5 +120,280 @@ index ba1754e02..a50376e2e 100644
BUS_NAME,
G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
--
2.23.0
2.26.2
From d8b4d72b89340dab46bdcb92ee54bde18dbb9ba9 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Fri, 24 Jan 2020 10:59:31 +0100
Subject: [PATCH 3/4] perf-tool: Spawn perf-tool-helper from gnome-shell
On Wayland, the display server is the Wayland compositor, i.e.
`gnome-shell` itself.
As a result, we cannot spawn `gnome-shell-perf-helper` before
`gnome-shell` is started, as `gnome-shell-perf-helper` needs to connect
to the display server.
So, instead of spawning `gnome-shell-perf-helper` from the perf tool,
start it from `gnome-shell` itself.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/941
---
js/ui/scripting.js | 51 ++++++++++++++++++++++------------
src/gnome-shell-perf-tool.in | 53 ------------------------------------
2 files changed, 34 insertions(+), 70 deletions(-)
diff --git a/js/ui/scripting.js b/js/ui/scripting.js
index d227b9ef4..eef8f3887 100644
--- a/js/ui/scripting.js
+++ b/js/ui/scripting.js
@@ -3,8 +3,10 @@
const { Gio, GLib, Meta, Shell } = imports.gi;
const Mainloop = imports.mainloop;
+const Config = imports.misc.config;
const Main = imports.ui.main;
const Params = imports.misc.params;
+const Util = imports.misc.util;
const { loadInterfaceXML } = imports.misc.fileUtils;
@@ -73,6 +75,12 @@ function _getPerfHelper() {
return _perfHelper;
}
+function _spawnPerfHelper() {
+ let path = Config.LIBEXECDIR;
+ let command = `${path}/gnome-shell-perf-helper`;
+ Util.trySpawnCommandLine(command);
+}
+
function _callRemote(obj, method, ...args) {
return new Promise((resolve, reject) => {
args.push((result, excp) => {
@@ -270,6 +278,25 @@ function _collect(scriptModule, outputFile) {
}
}
+async function _runPerfScript(scriptModule, outputFile) {
+ for (let step of scriptModule.run()) {
+ try {
+ await step; // eslint-disable-line no-await-in-loop
+ } catch (err) {
+ log(`Script failed: ${err}\n${err.stack}`);
+ Meta.exit(Meta.ExitCode.ERROR);
+ }
+ }
+
+ try {
+ _collect(scriptModule, outputFile);
+ } catch (err) {
+ log(`Script failed: ${err}\n${err.stack}`);
+ Meta.exit(Meta.ExitCode.ERROR);
+ }
+ Meta.exit(Meta.ExitCode.SUCCESS);
+}
+
/**
* runPerfScript
* @scriptModule: module object with run and finish functions
@@ -310,23 +337,13 @@ function _collect(scriptModule, outputFile) {
* After running the script and collecting statistics from the
* event log, GNOME Shell will exit.
**/
-async function runPerfScript(scriptModule, outputFile) {
+function runPerfScript(scriptModule, outputFile) {
Shell.PerfLog.get_default().set_enabled(true);
+ _spawnPerfHelper();
- for (let step of scriptModule.run()) {
- try {
- await step;
- } catch (err) {
- log(`Script failed: ${err}\n${err.stack}`);
- Meta.exit(Meta.ExitCode.ERROR);
- }
- }
-
- try {
- _collect(scriptModule, outputFile);
- } catch (err) {
- log(`Script failed: ${err}\n${err.stack}`);
- Meta.exit(Meta.ExitCode.ERROR);
- }
- Meta.exit(Meta.ExitCode.SUCCESS);
+ Gio.bus_watch_name(Gio.BusType.SESSION,
+ 'org.gnome.Shell.PerfHelper',
+ Gio.BusNameWatcherFlags.NONE,
+ () => _runPerfScript(scriptModule, outputFile),
+ null);
}
diff --git a/src/gnome-shell-perf-tool.in b/src/gnome-shell-perf-tool.in
index f4b48f730..050c66b30 100755
--- a/src/gnome-shell-perf-tool.in
+++ b/src/gnome-shell-perf-tool.in
@@ -24,52 +24,6 @@ def show_version(option, opt_str, value, parser):
print("GNOME Shell Performance Test @VERSION@")
sys.exit()
-def wait_for_dbus_name(wait_name):
- loop = GLib.MainLoop()
-
- def on_name_appeared(connection, name, new_owner, *args):
- if not (name == wait_name and new_owner != ''):
- return
- loop.quit()
- return
-
- watch_id = Gio.bus_watch_name(Gio.BusType.SESSION,
- wait_name,
- Gio.BusNameWatcherFlags.NONE,
- on_name_appeared,
- None)
-
- def on_timeout():
- print("\nFailed to start %s: timed out" % (wait_name,))
- sys.exit(1)
- GLib.timeout_add_seconds(7, on_timeout)
-
- loop.run()
- Gio.bus_unwatch_name(watch_id)
-
-PERF_HELPER_NAME = "org.gnome.Shell.PerfHelper"
-PERF_HELPER_IFACE = "org.gnome.Shell.PerfHelper"
-PERF_HELPER_PATH = "/org/gnome/Shell/PerfHelper"
-
-def start_perf_helper():
- self_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
- perf_helper_path = "@libexecdir@/gnome-shell-perf-helper"
-
- subprocess.Popen([perf_helper_path])
- wait_for_dbus_name (PERF_HELPER_NAME)
-
-def stop_perf_helper():
- bus = Gio.bus_get_sync(Gio.BusType.SESSION, None)
-
- proxy = Gio.DBusProxy.new_sync(bus,
- Gio.DBusProxyFlags.NONE,
- None,
- PERF_HELPER_NAME,
- PERF_HELPER_PATH,
- PERF_HELPER_IFACE,
- None)
- proxy.Exit()
-
def start_shell(perf_output=None):
# Set up environment
env = dict(os.environ)
@@ -204,8 +158,6 @@ def run_performance_test():
logs = []
metric_summaries = {}
- start_perf_helper()
-
for i in range(0, iters):
# We create an empty temporary file that the shell will overwrite
# with the contents.
@@ -217,14 +169,12 @@ def run_performance_test():
try:
normal_exit = run_shell(perf_output=output_file)
except:
- stop_perf_helper()
raise
finally:
if not normal_exit:
os.remove(output_file)
if not normal_exit:
- stop_perf_helper()
return False
try:
@@ -232,7 +182,6 @@ def run_performance_test():
output = json.load(f)
f.close()
except:
- stop_perf_helper()
raise
finally:
os.remove(output_file)
@@ -260,8 +209,6 @@ def run_performance_test():
logs.append(output['log'])
- stop_perf_helper()
-
if options.perf_output or options.perf_upload:
# Write a complete report, formatted as JSON. The Javascript/C code that
# generates the individual reports we are summarizing here is very careful
--
2.26.2
From 8090db0f29dc72e602be341d43b3113373404b21 Mon Sep 17 00:00:00 2001
From: Olivier Fourdan <ofourdan@redhat.com>
Date: Tue, 21 Jan 2020 11:05:58 +0100
Subject: [PATCH 4/4] perf-tool: Allow to run as a Wayland compositor
`gnome-shell-perf-tool` is initially designed to run on X11, using the
`--replace` option which does not work when gnome-shell is a Wayland
compositor.
A solution would be to run `gnome-shell-perf-tool` in place of just
`gnome-shell` to run the entire perf session under Wayland, but the
script `gnome-shell-perf-tool` does not spawn `gnome-shell` as a Wayladn
compositor, so that fails as well.
Add a `--wayland` option to `gnome-shell-perf-tool` so that it can
optionally spawn gnome-shell as a Wayland compositor so the whole perf
tool can be starred from a console with:
```
$ dbus-run-session -- gnome-shell-perf-tool --wayland
```
Alternatively, for testing purposes, it can also be started nested with:
```
$ dbus-run-session -- gnome-shell-perf-tool --nested
```
Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/2139
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/941
---
src/gnome-shell-perf-tool.in | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/src/gnome-shell-perf-tool.in b/src/gnome-shell-perf-tool.in
index 050c66b30..04072c4cd 100755
--- a/src/gnome-shell-perf-tool.in
+++ b/src/gnome-shell-perf-tool.in
@@ -45,6 +45,13 @@ def start_shell(perf_output=None):
if options.replace:
args.append('--replace')
+ if options.wayland or options.nested:
+ args.append('--wayland')
+ if options.nested:
+ args.append('--nested')
+ else:
+ args.append('--display-server')
+
return subprocess.Popen(args, env=env)
def run_shell(perf_output=None):
@@ -284,6 +291,10 @@ parser.add_option("", "--version", action="callback", callback=show_version,
parser.add_option("-r", "--replace", action="store_true",
help="Replace the running window manager")
+parser.add_option("-w", "--wayland", action="store_true",
+ help="Run as a Wayland compositor")
+parser.add_option("-n", "--nested", action="store_true",
+ help="Run as a Wayland nested compositor")
options, args = parser.parse_args()
--
2.26.2

View File

@ -1,6 +1,6 @@
Name: gnome-shell
Version: 3.32.2
Release: 14%{?dist}
Release: 20%{?dist}
Summary: Window management and application launching for GNOME
Group: User Interface/Desktops
@ -44,9 +44,21 @@ Patch46: 0001-a11y-Change-HC-icon-theme-first.patch
Patch47: perf-tool-wayland.patch
Patch48: 0001-padOsd-Re-query-action-labels-after-mode-switches.patch
Patch49: 0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch
Patch50: 0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch
Patch51: introspect-backports.patch
Patch52: 0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch
# Backport JS invalid access warnings (#1651894, #1663171, #1642482, #1637622)
Patch54: fix-invalid-access-warnings.patch
Patch55: more-spurious-allocation-warnings.patch
# Backport performance fixes under load (#1820760)
Patch60: 0001-environment-reduce-calls-to-g_time_zone_new_local.patch
Patch61: 0002-environment-Fix-date-conversion.patch
Patch62: 0003-shell-app-system-Monitor-for-icon-theme-changes.patch
Patch63: 0004-global-force-fsync-to-worker-thread-when-saving-stat.patch
Patch64: 0005-app-cache-add-ShellAppCache-for-GAppInfo-caching.patch
Patch65: 0006-js-Always-use-AppSystem-to-lookup-apps.patch
# suspend/resume fix on nvidia (#1663440)
Patch10001: 0001-background-refresh-after-suspend-on-wayland.patch
@ -227,6 +239,36 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
%{_mandir}/man1/%{name}.1.gz
%changelog
* Thu Jul 30 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-20
- Fix popupMenu keynav when NumLock is active
Resolves: #1840080
* Mon Jun 15 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-19
- Fix last backport
Resolves: #1847051
* Sun Jun 14 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-18
- Fix more spurious allocation warnings
Resolves: #1715845
* Fri May 22 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-17
- Really allow using perf-tool on wayland
Resolves: #1652178
- Fix timed login without user list
Resolves: #1668895
- Fix HighContrast/symbolic icon mixup
Resolves: #1794045
- Backport introspect API changes
Resolves: #1837413
* Fri Apr 17 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-16
- Drop bad upstream patch
Resolves: #1820760
* Wed Apr 08 2020 Florian Müllner <fmuellner@redhat.com> - 3.32.2-15
- Improve performance under load
Resolves: #1820760
* Wed Mar 04 2020 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-14
- Do not set Wacom LEDs through gnome-settings-daemon, rely on kernel driver
Resolves: #1687979