import gnome-shell-3.32.2-19.el8
This commit is contained in:
parent
1671fe97eb
commit
842e6632ac
25
SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch
Normal file
25
SOURCES/0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch
Normal file
@ -0,0 +1,25 @@
|
||||
From f5ddd0fc02e99597e4b8506ac35523a6fa8ac22f Mon Sep 17 00:00:00 2001
|
||||
From: rpm-build <rpm-build>
|
||||
Date: Wed, 4 Mar 2020 16:08:31 +0100
|
||||
Subject: [PATCH] Do not change Wacom LEDs through g-s-d
|
||||
|
||||
Let the wacom kernel driver sort it out by itself.
|
||||
---
|
||||
js/ui/windowManager.js | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
diff --git a/js/ui/windowManager.js b/js/ui/windowManager.js
|
||||
index dfe1b44..b2e938c 100644
|
||||
--- a/js/ui/windowManager.js
|
||||
+++ b/js/ui/windowManager.js
|
||||
@@ -1037,7 +1037,6 @@ var WindowManager = class {
|
||||
|
||||
if (this._gsdWacomProxy) {
|
||||
this._gsdWacomProxy.SetOLEDLabelsRemote(pad.get_device_node(), labels);
|
||||
- this._gsdWacomProxy.SetGroupModeLEDRemote(pad.get_device_node(), group, mode);
|
||||
}
|
||||
});
|
||||
|
||||
--
|
||||
2.24.1
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
33
SOURCES/0002-environment-Fix-date-conversion.patch
Normal file
33
SOURCES/0002-environment-Fix-date-conversion.patch
Normal 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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
66
SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch
Normal file
66
SOURCES/0006-js-Always-use-AppSystem-to-lookup-apps.patch
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
643
SOURCES/introspect-backports.patch
Normal file
643
SOURCES/introspect-backports.patch
Normal 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
|
||||
|
176
SOURCES/more-spurious-allocation-warnings.patch
Normal file
176
SOURCES/more-spurious-allocation-warnings.patch
Normal 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
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
Name: gnome-shell
|
||||
Version: 3.32.2
|
||||
Release: 13%{?dist}
|
||||
Release: 19%{?dist}
|
||||
Summary: Window management and application launching for GNOME
|
||||
|
||||
Group: User Interface/Desktops
|
||||
@ -43,9 +43,21 @@ Patch45: 0001-workspace-Pass-device-to-startDrag.patch
|
||||
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
|
||||
|
||||
# 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
|
||||
@ -226,6 +238,36 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
|
||||
%{_mandir}/man1/%{name}.1.gz
|
||||
|
||||
%changelog
|
||||
* 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
|
||||
|
||||
* Mon Dec 16 2019 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-13
|
||||
- Update pad OSD on mode switching
|
||||
Resolves: #1716774
|
||||
|
Loading…
Reference in New Issue
Block a user