import gnome-shell-40.6-1.el9

This commit is contained in:
CentOS Sources 2021-12-07 13:04:51 -05:00 committed by Stepan Oksanichenko
parent 0f58808657
commit 8eb6d5856b
6 changed files with 752 additions and 4 deletions

2
.gitignore vendored
View File

@ -1 +1 @@
SOURCES/gnome-shell-40.4.tar.xz
SOURCES/gnome-shell-40.6.tar.xz

View File

@ -1 +1 @@
41d5d915c880f6a62bf82354b01eba39be72d6d1 SOURCES/gnome-shell-40.4.tar.xz
0534bb62d92840522fd0c424747d157a38852ccd SOURCES/gnome-shell-40.6.tar.xz

View File

@ -0,0 +1,31 @@
From a9e79b1657dc7c1b702d7acc4d322539d2b8b6aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20=C3=85dahl?= <jadahl@gmail.com>
Date: Wed, 6 Oct 2021 10:00:43 +0200
Subject: [PATCH] main: Leak the GJS context and ShellGlobal
There are many crash-on-exit happening as a side effect of destroying
the GJS context. Work around these until we have a better solution by
leaking them.
---
src/main.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/main.c b/src/main.c
index 91e5493fd1..d62dda9627 100644
--- a/src/main.c
+++ b/src/main.c
@@ -508,9 +508,11 @@ main (int argc, char **argv)
ecode = meta_run ();
shell_profiler_shutdown ();
+#if 0
g_debug ("Doing final cleanup");
_shell_global_destroy_gjs_context (shell_global_get ());
g_object_unref (shell_global_get ());
+#endif
return ecode;
}
--
2.31.1

View File

@ -0,0 +1,35 @@
From 5033596c01e1d8fcdc9bd64a575a44f423b1ac51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Wed, 27 Oct 2021 15:18:20 +0200
Subject: [PATCH] welcomeDialog: Adapt dialog title
Use RHEL branding instead of the upstream GNOME XX one.
---
js/ui/welcomeDialog.js | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/js/ui/welcomeDialog.js b/js/ui/welcomeDialog.js
index 9d99f0035..17e2a277c 100644
--- a/js/ui/welcomeDialog.js
+++ b/js/ui/welcomeDialog.js
@@ -3,7 +3,6 @@
const { Clutter, GObject, Shell, St } = imports.gi;
-const Config = imports.misc.config;
const Dialog = imports.ui.dialog;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
@@ -32,8 +31,7 @@ class WelcomeDialog extends ModalDialog.ModalDialog {
}
_buildLayout() {
- const [majorVersion] = Config.PACKAGE_VERSION.split('.');
- const title = _('Welcome to GNOME %s').format(majorVersion);
+ const title = _('Welcome to Red Hat Enterprise Linux');
const description = _('If you want to learn your way around, check out the tour.');
const content = new Dialog.MessageDialogContent({ title, description });
--
2.32.0

View File

@ -0,0 +1,662 @@
From e7fe96d918ef75f59448664d7583eb51735be64d Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Aug 2021 13:25:57 -0400
Subject: [PATCH 1/3] extensionSystem: Get rid of _enabled boolean optimization
At the moment a session mode either allows extensions or it doesn't.
If it allows extensions, then the entire available list of
configured extensions get enabled as soon as the session mode is
entered.
Since enabling or disabling extensions is an all or nothing situation,
the code tracks whether extensions are already enabled when entering
the session mode, and if so, avoids iterating through the extension list
needlessly. It does this using a boolean named _enabled.
In the future, the extensions themselves will be given some say on
whether or not they should be enabled in a given session mode. This
means, the configured extension list may contain extensions that
shouldn't be enabled for a given session mode, and the _enabled boolean
will no longer be appropriated.
This commit drops the _enabled boolean optimization.
---
js/ui/extensionSystem.js | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 6b624fca0..9a8f1c9a2 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -1,56 +1,55 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
/* exported init connect disconnect */
const { GLib, Gio, GObject, Shell, St } = imports.gi;
const ByteArray = imports.byteArray;
const Signals = imports.signals;
const ExtensionDownloader = imports.ui.extensionDownloader;
const ExtensionUtils = imports.misc.extensionUtils;
const FileUtils = imports.misc.fileUtils;
const Main = imports.ui.main;
const MessageTray = imports.ui.messageTray;
const { ExtensionState, ExtensionType } = ExtensionUtils;
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
const DISABLED_EXTENSIONS_KEY = 'disabled-extensions';
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
const UPDATE_CHECK_TIMEOUT = 24 * 60 * 60; // 1 day in seconds
var ExtensionManager = class {
constructor() {
this._initialized = false;
- this._enabled = false;
this._updateNotified = false;
this._extensions = new Map();
this._unloadedExtensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
}
init() {
// The following file should exist for a period of time when extensions
// are enabled after start. If it exists, then the systemd unit will
// disable extensions should gnome-shell crash.
// Should the file already exist from a previous login, then this is OK.
let disableFilename = GLib.build_filenamev([GLib.get_user_runtime_dir(), 'gnome-shell-disable-extensions']);
let disableFile = Gio.File.new_for_path(disableFilename);
try {
disableFile.create(Gio.FileCreateFlags.REPLACE_DESTINATION, null);
} catch (e) {
log('Failed to create file %s: %s'.format(disableFilename, e.message));
}
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
disableFile.delete(null);
return GLib.SOURCE_REMOVE;
});
this._installExtensionUpdates();
this._sessionUpdated();
@@ -563,85 +562,76 @@ var ExtensionManager = class {
this._enabledExtensions = this._getEnabledExtensions();
let perUserDir = Gio.File.new_for_path(global.userdatadir);
FileUtils.collectFromDatadirs('extensions', true, (dir, info) => {
let fileType = info.get_file_type();
if (fileType != Gio.FileType.DIRECTORY)
return;
let uuid = info.get_name();
let existing = this.lookup(uuid);
if (existing) {
log('Extension %s already installed in %s. %s will not be loaded'.format(uuid, existing.path, dir.get_path()));
return;
}
let extension;
let type = dir.has_prefix(perUserDir)
? ExtensionType.PER_USER
: ExtensionType.SYSTEM;
try {
extension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
logError(e, 'Could not load extension %s'.format(uuid));
return;
}
this.loadExtension(extension);
});
}
_enableAllExtensions() {
- if (this._enabled)
- return;
-
if (!this._initialized) {
this._loadExtensions();
this._initialized = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
- this._enabled = true;
}
_disableAllExtensions() {
- if (!this._enabled)
- return;
-
if (this._initialized) {
this._extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
}
-
- this._enabled = false;
}
_sessionUpdated() {
// For now sessionMode.allowExtensions controls extensions from both the
// 'enabled-extensions' preference and the sessionMode.enabledExtensions
// property; it might make sense to make enabledExtensions independent
// from allowExtensions in the future
if (Main.sessionMode.allowExtensions) {
// Take care of added or removed sessionMode extensions
this._onEnabledExtensionsChanged();
this._enableAllExtensions();
} else {
this._disableAllExtensions();
}
}
};
Signals.addSignalMethods(ExtensionManager.prototype);
const ExtensionUpdateSource = GObject.registerClass(
class ExtensionUpdateSource extends MessageTray.Source {
_init() {
let appSys = Shell.AppSystem.get_default();
this._app = appSys.lookup_app('org.gnome.Extensions.desktop');
super._init(this._app.get_name());
}
getIcon() {
return this._app.app_info.get_icon();
}
--
2.31.1
From c96d908167b8bb088454e0e839d1c2d6e3638676 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Sat, 28 Aug 2021 13:54:39 -0400
Subject: [PATCH 2/3] extensionSystem: Allow extensions to run on the login
screen
At the moment it's not realy possible to extend the login screen to do
things it doesn't have built-in support for. This means in order
to support niche use cases, those cases have to change the main
code base. For instance, oVirt and Vmware deployments want to be able
to automaticaly log in guest VMs when a user pre-authenticates through a
console on a management host. To support those use cases, we added
code to the login screen directly, even though most machines will never
be associated with oVirt or Vmware management hosts.
We also get requests from e.g. government users that need certain features
at the login screen that wouldn't get used much outside of government
deployments. For instance, we've gotten requests that a machine contains
prominently displays that it has "Top Secret" information.
All of these use cases seem like they would better handled via
extensions that could be installed in the specific deployments. The
problem is extensions only run in the user session, and get
disabled at the login screen automatically.
This commit changes that. Now extensions can specify in their metadata
via a new sessionModes property, which modes that want to run in. For
backward compatibility, if an extension doesn't specify which session
modes it works in, its assumed the extension only works in the user
session.
---
js/ui/extensionSystem.js | 33 +++++++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 9a8f1c9a2..bbf322ee7 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -47,120 +47,142 @@ var ExtensionManager = class {
}
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 60, () => {
disableFile.delete(null);
return GLib.SOURCE_REMOVE;
});
this._installExtensionUpdates();
this._sessionUpdated();
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => {
ExtensionDownloader.checkForUpdates();
return GLib.SOURCE_CONTINUE;
});
ExtensionDownloader.checkForUpdates();
}
get updatesSupported() {
const appSys = Shell.AppSystem.get_default();
return appSys.lookup_app('org.gnome.Extensions.desktop') !== null;
}
lookup(uuid) {
return this._extensions.get(uuid);
}
getUuids() {
return [...this._extensions.keys()];
}
+ _extensionSupportsSessionMode(uuid) {
+ const extension = this.lookup(uuid);
+ if (!extension)
+ return false;
+
+ if (extension.sessionModes.includes(Main.sessionMode.currentMode))
+ return true;
+ if (extension.sessionModes.includes(Main.sessionMode.parentMode))
+ return true;
+ return false;
+ }
+
+ _sessionModeCanUseExtension(uuid) {
+ if (!Main.sessionMode.allowExtensions)
+ return false;
+
+ if (!this._extensionSupportsSessionMode(uuid))
+ return false;
+
+ return true;
+ }
+
_callExtensionDisable(uuid) {
let extension = this.lookup(uuid);
if (!extension)
return;
if (extension.state != ExtensionState.ENABLED)
return;
// "Rebase" the extension order by disabling and then enabling extensions
// in order to help prevent conflicts.
// Example:
// order = [A, B, C, D, E]
// user disables C
// this should: disable E, disable D, disable C, enable D, enable E
let orderIdx = this._extensionOrder.indexOf(uuid);
let order = this._extensionOrder.slice(orderIdx + 1);
let orderReversed = order.slice().reverse();
for (let i = 0; i < orderReversed.length; i++) {
let otherUuid = orderReversed[i];
try {
this.lookup(otherUuid).stateObj.disable();
} catch (e) {
this.logExtensionError(otherUuid, e);
}
}
try {
extension.stateObj.disable();
} catch (e) {
this.logExtensionError(uuid, e);
}
if (extension.stylesheet) {
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
theme.unload_stylesheet(extension.stylesheet);
delete extension.stylesheet;
}
for (let i = 0; i < order.length; i++) {
let otherUuid = order[i];
try {
this.lookup(otherUuid).stateObj.enable();
} catch (e) {
this.logExtensionError(otherUuid, e);
}
}
this._extensionOrder.splice(orderIdx, 1);
if (extension.state != ExtensionState.ERROR) {
extension.state = ExtensionState.DISABLED;
this.emit('extension-state-changed', extension);
}
}
_callExtensionEnable(uuid) {
- if (!Main.sessionMode.allowExtensions)
+ if (!this._sessionModeCanUseExtension(uuid))
return;
let extension = this.lookup(uuid);
if (!extension)
return;
if (extension.state == ExtensionState.INITIALIZED)
this._callExtensionInit(uuid);
if (extension.state != ExtensionState.DISABLED)
return;
let stylesheetNames = ['%s.css'.format(global.session_mode), 'stylesheet.css'];
let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
for (let i = 0; i < stylesheetNames.length; i++) {
try {
let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
theme.load_stylesheet(stylesheetFile);
extension.stylesheet = stylesheetFile;
break;
} catch (e) {
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
continue; // not an error
this.logExtensionError(uuid, e);
return;
}
}
try {
extension.stateObj.enable();
@@ -288,60 +310,61 @@ var ExtensionManager = class {
} catch (e) {
throw new Error('Failed to load metadata.json: %s'.format(e.toString()));
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error('Failed to parse metadata.json: %s'.format(e.toString()));
}
let requiredProperties = ['uuid', 'name', 'description', 'shell-version'];
for (let i = 0; i < requiredProperties.length; i++) {
let prop = requiredProperties[i];
if (!meta[prop])
throw new Error('missing "%s" property in metadata.json'.format(prop));
}
if (uuid != meta.uuid)
throw new Error('uuid "%s" from metadata.json does not match directory name "%s"'.format(meta.uuid, uuid));
let extension = {
metadata: meta,
uuid: meta.uuid,
type,
dir,
path: dir.get_path(),
error: '',
hasPrefs: dir.get_child('prefs.js').query_exists(null),
hasUpdate: false,
canChange: false,
+ sessionModes: meta['session-modes'] ? meta['session-modes'] : [ 'user' ],
};
this._extensions.set(uuid, extension);
return extension;
}
_canLoad(extension) {
if (!this._unloadedExtensions.has(extension.uuid))
return true;
const version = this._unloadedExtensions.get(extension.uuid);
return extension.metadata.version === version;
}
loadExtension(extension) {
// Default to error, we set success as the last step
extension.state = ExtensionState.ERROR;
let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
extension.state = ExtensionState.OUT_OF_DATE;
} else if (!this._canLoad(extension)) {
this.logExtensionError(extension.uuid, new Error(
'A different version was loaded previously. You need to log out for changes to take effect.'));
} else {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
if (!this._callExtensionInit(extension.uuid))
return;
@@ -372,61 +395,61 @@ var ExtensionManager = class {
// If we did install an importer, it is now cached and it's
// impossible to load a different version
if (type === ExtensionType.PER_USER && extension.imports)
this._unloadedExtensions.set(uuid, extension.metadata.version);
this._extensions.delete(uuid);
return true;
}
reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid, dir, type } = oldExtension;
// Then unload the old extension.
this.unloadExtension(oldExtension);
// Now, recreate the extension and load it.
let newExtension;
try {
newExtension = this.createExtensionObject(uuid, dir, type);
} catch (e) {
this.logExtensionError(uuid, e);
return;
}
this.loadExtension(newExtension);
}
_callExtensionInit(uuid) {
- if (!Main.sessionMode.allowExtensions)
+ if (!this._sessionModeCanUseExtension(uuid))
return false;
let extension = this.lookup(uuid);
if (!extension)
throw new Error("Extension was not properly created. Call createExtensionObject first");
let dir = extension.dir;
let extensionJs = dir.get_child('extension.js');
if (!extensionJs.query_exists(null)) {
this.logExtensionError(uuid, new Error('Missing extension.js'));
return false;
}
let extensionModule;
let extensionState = null;
ExtensionUtils.installImporter(extension);
try {
extensionModule = extension.imports.extension;
} catch (e) {
this.logExtensionError(uuid, e);
return false;
}
if (extensionModule.init) {
try {
extensionState = extensionModule.init(extension);
} catch (e) {
this.logExtensionError(uuid, e);
return false;
@@ -461,67 +484,69 @@ var ExtensionManager = class {
: ENABLED_EXTENSIONS_KEY;
extension.canChange =
!hasError &&
global.settings.is_writable(changeKey) &&
(isMode || !modeOnly);
}
_getEnabledExtensions() {
let extensions = this._getModeExtensions();
if (!global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
extensions = extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
// filter out 'disabled-extensions' which takes precedence
let disabledExtensions = global.settings.get_strv(DISABLED_EXTENSIONS_KEY);
return extensions.filter(item => !disabledExtensions.includes(item));
}
_onUserExtensionsEnabledChanged() {
this._onEnabledExtensionsChanged();
this._onSettingsWritableChanged();
}
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
// Find and enable all the newly enabled extensions: UUIDs found in the
// new setting, but not in the old one.
newEnabledExtensions
- .filter(uuid => !this._enabledExtensions.includes(uuid))
+ .filter(uuid => !this._enabledExtensions.includes(uuid) &&
+ this._extensionSupportsSessionMode(uuid))
.forEach(uuid => this._callExtensionEnable(uuid));
// Find and disable all the newly disabled extensions: UUIDs found in the
// old setting, but not in the new one.
this._extensionOrder
- .filter(uuid => !newEnabledExtensions.includes(uuid))
+ .filter(uuid => !newEnabledExtensions.includes(uuid) ||
+ !this._extensionSupportsSessionMode(uuid))
.reverse().forEach(uuid => this._callExtensionDisable(uuid));
this._enabledExtensions = newEnabledExtensions;
}
_onSettingsWritableChanged() {
for (let extension of this._extensions.values()) {
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
}
_onVersionValidationChanged() {
// Disabling extensions modifies the order array, so use a copy
let extensionOrder = this._extensionOrder.slice();
// Disable enabled extensions in the reverse order first to avoid
// the "rebasing" done in _callExtensionDisable...
extensionOrder.slice().reverse().forEach(uuid => {
this._callExtensionDisable(uuid);
});
// ...and then reload and enable extensions in the correct order again.
[...this._extensions.values()].sort((a, b) => {
return extensionOrder.indexOf(a.uuid) - extensionOrder.indexOf(b.uuid);
}).forEach(extension => this.reloadExtension(extension));
}
_installExtensionUpdates() {
if (!this.updatesSupported)
--
2.31.1
From 407c537a5cd14c9e9494d954f27eacfa1589aed5 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Aug 2021 15:31:00 -0400
Subject: [PATCH 3/3] sessionMode: Allow extensions at the login and unlock
screens
Now extensions can specify which session modes they work in,
but specifying the login screen or unlock screen session modes in
an extensions metadata still won't work, because those session
modes disallow extensions.
This commit fixes that.
---
js/ui/sessionMode.js | 2 ++
1 file changed, 2 insertions(+)
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index 4d4fb2444..0534fd1d4 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -16,76 +16,78 @@ const _modes = {
'restrictive': {
parentMode: null,
stylesheetName: 'gnome-shell.css',
themeResourceName: 'gnome-shell-theme.gresource',
hasOverview: false,
showCalendarEvents: false,
showWelcomeDialog: false,
allowSettings: false,
allowExtensions: false,
allowScreencast: false,
enabledExtensions: [],
hasRunDialog: false,
hasWorkspaces: false,
hasWindows: false,
hasNotifications: false,
hasWmMenus: false,
isLocked: false,
isGreeter: false,
isPrimary: false,
unlockDialog: null,
components: [],
panel: {
left: [],
center: [],
right: [],
},
panelStyle: null,
},
'gdm': {
+ allowExtensions: true,
hasNotifications: true,
isGreeter: true,
isPrimary: true,
unlockDialog: imports.gdm.loginDialog.LoginDialog,
components: Config.HAVE_NETWORKMANAGER
? ['networkAgent', 'polkitAgent']
: ['polkitAgent'],
panel: {
left: [],
center: ['dateMenu'],
right: ['dwellClick', 'a11y', 'keyboard', 'aggregateMenu'],
},
panelStyle: 'login-screen',
},
'unlock-dialog': {
+ allowExtensions: true,
isLocked: true,
unlockDialog: undefined,
components: ['polkitAgent', 'telepathyClient'],
panel: {
left: [],
center: [],
right: ['dwellClick', 'a11y', 'keyboard', 'aggregateMenu'],
},
panelStyle: 'unlock-screen',
},
'user': {
hasOverview: true,
showCalendarEvents: true,
showWelcomeDialog: true,
allowSettings: true,
allowExtensions: true,
allowScreencast: true,
hasRunDialog: true,
hasWorkspaces: true,
hasWindows: true,
hasWmMenus: true,
hasNotifications: true,
isLocked: false,
isPrimary: true,
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: Config.HAVE_NETWORKMANAGER
? ['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager']
: ['polkitAgent', 'telepathyClient',
--
2.31.1

View File

@ -1,8 +1,8 @@
%global tarball_version %%(echo %{version} | tr '~' '.')
Name: gnome-shell
Version: 40.4
Release: 2%{?dist}
Version: 40.6
Release: 1%{?dist}
Summary: Window management and application launching for GNOME
License: GPLv2+
@ -21,6 +21,7 @@ Patch12: disable-unlock-entry-until-question.patch
Patch13: 0001-loginDialog-make-info-messages-themed.patch
Patch14: support-choicelist-extension.patch
Patch15: gdm-networking.patch
Patch16: login-screen-extensions.patch
# Misc.
Patch30: 0001-panel-add-an-icon-to-the-ActivitiesButton.patch
@ -33,6 +34,8 @@ Patch36: 0001-st-texture-cache-purge-on-resume.patch
Patch37: 0001-Update-generated-stylesheets.patch
Patch38: add-power-profiles-menu.patch
Patch39: 0001-status-network-Use-wwan-settings-panel-for-GSM-LTE-M.patch
Patch40: 0001-welcomeDialog-Adapt-dialog-title.patch
Patch41: 0001-main-Leak-the-GJS-context-and-ShellGlobal.patch
%define eds_version 3.33.1
%define gnome_desktop_version 3.35.91
@ -251,6 +254,23 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
%{_mandir}/man1/gnome-shell.1*
%changelog
* Thu Nov 04 2021 Florian Müllner <fmuellner@redhat.com> - 40.6-1
- Update to 40.6
- Work around crashy tear down
Resolves: #2008065
* Wed Oct 27 2021 Florian Müllner <fmuellner@redhat.com> - 40.4-5
- Adapt welcome dialog title
Resolves: #2013989
* Wed Oct 13 2021 Ray Strode <rstrode@redhat.com> - 40.4-4
- Ensure extensions are reenabled after unlock
Resolves: #2013801
* Mon Sep 27 2021 Ray Strode <rstrode@redhat.com> - 40.4-3
- Allow extensions at the login screen
Related: #2006985
* Thu Aug 19 2021 Florian Müllner <fmuellner@redhat.com> - 40.4-2
- Use wwan setting panel for GSM/LTE modems
Resolves: #1995560