From 68628fa4d5de6730f4e29a6461c2d87345503de2 Mon Sep 17 00:00:00 2001 From: eabdullin Date: Mon, 15 Sep 2025 12:01:33 +0000 Subject: [PATCH] import CS gnome-shell-40.10-28.el9 --- ...1-Support-conflicting-session-dialog.patch | 402 ++++++++++++++++++ ...-theme-Reuse-stylesheets-if-possible.patch | 115 +++++ ...tionally-allow-restart-shutdown-on-l.patch | 63 +++ SPECS/gnome-shell.spec | 22 +- 4 files changed, 601 insertions(+), 1 deletion(-) create mode 100644 SOURCES/0001-Support-conflicting-session-dialog.patch create mode 100644 SOURCES/0001-st-theme-Reuse-stylesheets-if-possible.patch create mode 100644 SOURCES/0001-systemActions-Optionally-allow-restart-shutdown-on-l.patch diff --git a/SOURCES/0001-Support-conflicting-session-dialog.patch b/SOURCES/0001-Support-conflicting-session-dialog.patch new file mode 100644 index 0000000..f942064 --- /dev/null +++ b/SOURCES/0001-Support-conflicting-session-dialog.patch @@ -0,0 +1,402 @@ +From fd6f5b9834ffbd417b0543ac89ae0f8aeb67ff04 Mon Sep 17 00:00:00 2001 +From: Joan Torres +Date: Thu, 8 May 2025 12:51:58 +0200 +Subject: [PATCH 1/4] loginManager: Add session-removed signal and getSession + method + +These changes will be used by the next commit when displaying a +conflicting session dialog. + +session-removed signal will be used to close the conflicting session dialog +if it's not needed anymore. + +getSession method will be used when a session is opened, to check if +there's already a conflicting opened session. + +Part-of: +--- + js/misc/loginManager.js | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/js/misc/loginManager.js b/js/misc/loginManager.js +index 55e928986..3a91a4e8c 100644 +--- a/js/misc/loginManager.js ++++ b/js/misc/loginManager.js +@@ -97,6 +97,8 @@ var LoginManagerSystemd = class { + '/org/freedesktop/login1/user/self'); + this._proxy.connectSignal('PrepareForSleep', + this._prepareForSleep.bind(this)); ++ this._proxy.connectSignal('SessionRemoved', ++ this._sessionRemoved.bind(this)); + } + + getCurrentSessionProxy(callback) { +@@ -184,6 +186,10 @@ var LoginManagerSystemd = class { + }); + } + ++ getSession(objectPath) { ++ return new SystemdLoginSession(Gio.DBus.system, 'org.freedesktop.login1', objectPath); ++ } ++ + suspend() { + this._proxy.SuspendRemote(true); + } +@@ -206,6 +212,10 @@ var LoginManagerSystemd = class { + _prepareForSleep(proxy, sender, [aboutToSuspend]) { + this.emit('prepare-for-sleep', aboutToSuspend); + } ++ ++ _sessionRemoved(proxy, sender, [sessionId]) { ++ this.emit('session-removed', sessionId); ++ } + }; + Signals.addSignalMethods(LoginManagerSystemd.prototype); + +@@ -231,6 +241,10 @@ var LoginManagerDummy = class { + asyncCallback([]); + } + ++ getSession(_objectPath) { ++ return null; ++ } ++ + suspend() { + this.emit('prepare-for-sleep', true); + this.emit('prepare-for-sleep', false); +-- +2.49.0 + + +From f7d21a1ed99758c5f855adf9e0404a805f0fe497 Mon Sep 17 00:00:00 2001 +From: Joan Torres +Date: Thu, 8 May 2025 13:10:19 +0200 +Subject: [PATCH 2/4] loginDialog: Add ConflictingSessionDialog + +This dialog will be used by the next commit when a session is being opened but +there's already a conflicting session opened. + +Part-of: +--- + .../org.freedesktop.login1.Session.xml | 1 + + js/gdm/loginDialog.js | 64 +++++++++++++++++++ + 2 files changed, 65 insertions(+) + +diff --git a/data/dbus-interfaces/org.freedesktop.login1.Session.xml b/data/dbus-interfaces/org.freedesktop.login1.Session.xml +index 6fab81794..ecab4bbaa 100644 +--- a/data/dbus-interfaces/org.freedesktop.login1.Session.xml ++++ b/data/dbus-interfaces/org.freedesktop.login1.Session.xml +@@ -5,6 +5,7 @@ + + + ++ + + + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index 241721ff7..674ff24a5 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -28,6 +28,7 @@ const GdmUtil = imports.gdm.util; + const Layout = imports.ui.layout; + const LoginManager = imports.misc.loginManager; + const Main = imports.ui.main; ++const ModalDialog = imports.ui.modalDialog; + const PopupMenu = imports.ui.popupMenu; + const Realmd = imports.gdm.realmd; + const UserWidget = imports.ui.userWidget; +@@ -400,6 +401,69 @@ var SessionMenuButton = GObject.registerClass({ + } + }); + ++var ConflictingSessionDialog = GObject.registerClass({ ++ Signals: { ++ 'cancel': {}, ++ 'force-stop': {}, ++ }, ++}, class ConflictingSessionDialog extends ModalDialog.ModalDialog { ++ _init(conflictingSession) { ++ super._init(); ++ ++ const userName = conflictingSession.Name; ++ let bannerText; ++ /* Translators: is running for */ ++ bannerText = _('Login is not possible because a session is already running for %s. To login, you must log out from the session or force stop it.').format(userName); ++ ++ let textLayout = new St.BoxLayout({ ++ vertical: true, ++ x_expand: true, ++ style: 'spacing: 20px;', ++ }); ++ ++ let title = new St.Label({ ++ text: _('Session Already Running'), ++ style: 'text-align: center;' ++ + 'font-size: 18pt;' ++ + 'font-weight: 800;' ++ + 'margin-bottom: 5px;' }); ++ ++ let banner = new St.Label({ ++ text: bannerText, ++ style: 'text-align: center', ++ }); ++ banner.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; ++ banner.clutter_text.line_wrap = true; ++ ++ let warningBanner = new St.Label({ ++ text: _('Force stopping will quit any running apps and processes, and could result in data loss'), ++ style: 'text-align: center; color: #f57900;', ++ }); ++ warningBanner.clutter_text.ellipsize = Pango.EllipsizeMode.NONE; ++ warningBanner.clutter_text.line_wrap = true; ++ ++ textLayout.add_child(title); ++ textLayout.add_child(banner); ++ textLayout.add_child(warningBanner); ++ this.contentLayout.add_child(textLayout); ++ ++ this.addButton({ ++ label: _('Cancel'), ++ action: () => { ++ this.emit('cancel'); ++ }, ++ key: Clutter.KEY_Escape, ++ default: true, ++ }); ++ this.addButton({ ++ label: _('Force Stop'), ++ action: () => { ++ this.emit('force-stop'); ++ }, ++ }); ++ } ++}); ++ + var LoginDialog = GObject.registerClass({ + Signals: { + 'failed': {}, +-- +2.49.0 + + +From d849667b91d252cc9e029e8e1b2aaf4045e3890c Mon Sep 17 00:00:00 2001 +From: Joan Torres +Date: Thu, 8 May 2025 13:17:40 +0200 +Subject: [PATCH 3/4] loginDialog: On login, allow logout a conflicting session + +When opening a session, find if there's already a session opened for the +same user with the help of Loginmanager. +When it's found, display the conflicting session dialog. + +The logout dialog allows shutting down the conflicting session using the +greeter dbus method "StopConflictingSession". + +If the dialog is already opened and the conflicting session has been +closed on its side, the new session will start. + +Part-of: +--- + js/gdm/loginDialog.js | 77 ++++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 73 insertions(+), 4 deletions(-) + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index 674ff24a5..25b86880d 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -914,8 +914,8 @@ var LoginDialog = GObject.registerClass({ + + this._defaultSessionChangedId = this._greeter.connect('default-session-name-changed', + this._onDefaultSessionChanged.bind(this)); +- this._sessionOpenedId = this._greeter.connect('session-opened', +- this._onSessionOpened.bind(this)); ++ this._sessionOpenedId = this._greeter.connect('session-opened-with-session-id', ++ this._onSessionOpenedWithSessionId.bind(this)); + this._timedLoginRequestedId = this._greeter.connect('timed-login-requested', + this._onTimedLoginRequested.bind(this)); + } +@@ -1053,6 +1053,28 @@ var LoginDialog = GObject.registerClass({ + }); + } + ++ _showConflictingSessionDialog(serviceName, conflictingSession) { ++ let conflictingSessionDialog = new ConflictingSessionDialog(conflictingSession); ++ ++ conflictingSessionDialog.connect('cancel', () => { ++ this._authPrompt.reset(); ++ conflictingSessionDialog.close(); ++ }); ++ conflictingSessionDialog.connect('force-stop', () => { ++ this._greeter.call_stop_conflicting_session_sync(null); ++ }); ++ ++ const loginManager = LoginManager.getLoginManager(); ++ loginManager.connect('session-removed', (lm, sessionId) => { ++ if (sessionId === conflictingSession.Id) { ++ conflictingSessionDialog.close(); ++ this._authPrompt.finish(() => this._startSession(serviceName)); ++ } ++ }, conflictingSessionDialog); ++ ++ conflictingSessionDialog.open(); ++ } ++ + _startSession(serviceName) { + this._bindOpacity(); + this.ease({ +@@ -1066,8 +1088,55 @@ var LoginDialog = GObject.registerClass({ + }); + } + +- _onSessionOpened(client, serviceName) { +- this._authPrompt.finish(() => this._startSession(serviceName)); ++ _listSessions() { ++ const loginManager = LoginManager.getLoginManager(); ++ return new Promise(resolve => { ++ loginManager.listSessions(sessions => { ++ resolve(sessions); ++ }); ++ }); ++ } ++ ++ async _findConflictingSession(startingSessionId) { ++ const loginManager = LoginManager.getLoginManager(); ++ const sessions = await this._listSessions(); ++ const [, , startingSessionOwner, ,] = sessions.find(([id, , , ,]) => id === startingSessionId); ++ for (const session of sessions.map(([id, , user, , path]) => ({id, user, path}))) { ++ if (startingSessionId === session.id) ++ continue; ++ ++ if (startingSessionOwner !== session.user) ++ continue; ++ ++ const sessionProxy = loginManager.getSession(session.path); ++ ++ if (sessionProxy.Type !== 'wayland' && sessionProxy.Type !== 'x11') ++ continue; ++ ++ if (sessionProxy.State !== 'active' && sessionProxy.State !== 'online') ++ continue; ++ ++ return sessionProxy; ++ } ++ ++ return null; ++ } ++ ++ async _onSessionOpenedWithSessionId(client, serviceName, sessionId) { ++ try { ++ if (sessionId) { ++ const conflictingSession = await this._findConflictingSession(sessionId); ++ if (conflictingSession) { ++ this._showConflictingSessionDialog(serviceName, conflictingSession); ++ return; ++ } ++ } ++ ++ this._authPrompt.finish(() => this._startSession(serviceName)); ++ } catch (error) { ++ logError(error, `Failed to start session '${sessionId}'`); ++ this._authPrompt.reset(); ++ } + } + + _waitForItemForUser(userName) { +-- +2.49.0 + + +From b5dc399c0cdbecad7bd91bbae2287154e934981a Mon Sep 17 00:00:00 2001 +From: Joan Torres +Date: Thu, 8 May 2025 13:22:30 +0200 +Subject: [PATCH 4/4] loginDialog: Close conflicting session dialog after 60 + secs + +When the stop conflicting session dialog is opened, use a timeout of 60 +seconds to close it. +This is an attempt to keep security in the situation where the user leaves, +the system is left unsupervised and the dialog is opened; allowing anyone +to stop the old session and start a new session. + +When the dialog is closed by the timeout, a notification apperars informing +about that. + +Part-of: +--- + js/gdm/loginDialog.js | 32 ++++++++++++++++++++++++++++++++ + 1 file changed, 32 insertions(+) + +diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js +index 25b86880d..83a3bb09d 100644 +--- a/js/gdm/loginDialog.js ++++ b/js/gdm/loginDialog.js +@@ -28,6 +28,7 @@ const GdmUtil = imports.gdm.util; + const Layout = imports.ui.layout; + const LoginManager = imports.misc.loginManager; + const Main = imports.ui.main; ++const MessageTray = imports.ui.messageTray; + const ModalDialog = imports.ui.modalDialog; + const PopupMenu = imports.ui.popupMenu; + const Realmd = imports.gdm.realmd; +@@ -36,6 +37,7 @@ const UserWidget = imports.ui.userWidget; + const _FADE_ANIMATION_TIME = 250; + const _SCROLL_ANIMATION_TIME = 500; + const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; ++const _CONFLICTING_SESSION_DIALOG_TIMEOUT = 60; + + var UserListItem = GObject.registerClass({ + Signals: { 'activate': {} }, +@@ -1044,6 +1046,22 @@ var LoginDialog = GObject.registerClass({ + }); + } + ++ _notifyConflictingSessionDialogClosed() { ++ const source = new MessageTray.SystemNotificationSource(); ++ Main.messageTray.add(source); ++ ++ this._conflictingSessionNotification = new MessageTray.Notification(source, ++ _('Login Attempt Timed Out'), ++ _('Login took too long, please try again')); ++ this._conflictingSessionNotification.setUrgency(MessageTray.Urgency.CRITICAL); ++ this._conflictingSessionNotification.setTransient(true); ++ this._conflictingSessionNotification.connect('destroy', () => { ++ this._conflictingSessionNotification = null; ++ }); ++ ++ source.showNotification(this._conflictingSessionNotification); ++ } ++ + _showConflictingSessionDialog(serviceName, conflictingSession) { + let conflictingSessionDialog = new ConflictingSessionDialog(conflictingSession); + +@@ -1063,6 +1081,17 @@ var LoginDialog = GObject.registerClass({ + } + }, conflictingSessionDialog); + ++ const closeDialogTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, _CONFLICTING_SESSION_DIALOG_TIMEOUT, () => { ++ this._notifyConflictingSessionDialogClosed(); ++ conflictingSessionDialog.close(); ++ this._authPrompt.reset(); ++ return GLib.SOURCE_REMOVE; ++ }); ++ ++ conflictingSessionDialog.connect('closed', () => { ++ GLib.source_remove(closeDialogTimeoutId); ++ }); ++ + conflictingSessionDialog.open(); + } + +@@ -1318,6 +1347,9 @@ var LoginDialog = GObject.registerClass({ + + this._updateCancelButton(); + ++ if (this._conflictingSessionNotification) ++ this._conflictingSessionNotification.destroy(); ++ + let batch = new Batch.ConcurrentBatch(this, [GdmUtil.cloneAndFadeOutActor(this._userSelectionBox), + this._beginVerificationForItem(activatedItem)]); + batch.run(); +-- +2.49.0 + diff --git a/SOURCES/0001-st-theme-Reuse-stylesheets-if-possible.patch b/SOURCES/0001-st-theme-Reuse-stylesheets-if-possible.patch new file mode 100644 index 0000000..6563ae8 --- /dev/null +++ b/SOURCES/0001-st-theme-Reuse-stylesheets-if-possible.patch @@ -0,0 +1,115 @@ +From 11a28c3df5cd0afb254d5f1f68dcb923b97d09ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 29 Jan 2025 02:46:44 +0100 +Subject: [PATCH] st/theme: Reuse stylesheets if possible + +The following happens when processing an `@import()` rule: + + 1. `_st_theme_resolve_url()` to resolve file + 2. `insert_stylesheet()` to track file/sheet + a. take ownership of file/sheet (ref) + b. use file as key in `stylesheets_by_file` hash table + c. use file as value in `files_by_stylesheet` hash table + 3. release reference to file + +This leads to a refcount error when importing a file that +was already parsed before: + + 1. file start with refcount 1 + 2. `insert_stylesheet()` + a. increases refcount to 2 + b. inserting into `stylesheets_by_file` *decreases* the + passed-in key if the key already exists + c. `files_by_stylesheet` now tracks a file with recount 1 + 3. releases the last reference to file + +The file object tracked in `files_by_stylesheet` is now invalid, +and accessing it results in a crash. + +Avoid this issue by reusing existing stylesheets, so we don't insert +a stylesheet that's already tracked. + +As a side-effect, this also saves us from re-parsing the same file +unnecessarily. + +Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/7306 +Part-of: +--- + src/st/st-theme.c | 32 ++++++++++++++++++++++++++------ + 1 file changed, 26 insertions(+), 6 deletions(-) + +diff --git a/src/st/st-theme.c b/src/st/st-theme.c +index 20d42fd334..5db35645bf 100644 +--- a/src/st/st-theme.c ++++ b/src/st/st-theme.c +@@ -250,6 +250,27 @@ insert_stylesheet (StTheme *theme, + g_hash_table_insert (theme->files_by_stylesheet, stylesheet, file); + } + ++static CRStyleSheet * ++resolve_stylesheet (StTheme *theme, ++ GFile *file, ++ GError **error) ++{ ++ CRStyleSheet *sheet; ++ ++ sheet = g_hash_table_lookup (theme->stylesheets_by_file, file); ++ if (sheet) ++ { ++ cr_stylesheet_ref (sheet); ++ return sheet; ++ } ++ ++ sheet = parse_stylesheet (file, error); ++ if (sheet) ++ insert_stylesheet (theme, file, sheet); ++ ++ return sheet; ++} ++ + /** + * st_theme_load_stylesheet: + * @theme: a #StTheme +@@ -267,13 +288,12 @@ st_theme_load_stylesheet (StTheme *theme, + { + CRStyleSheet *stylesheet; + +- stylesheet = parse_stylesheet (file, error); ++ stylesheet = resolve_stylesheet (theme, file, error); + if (!stylesheet) + return FALSE; + + stylesheet->app_data = GUINT_TO_POINTER (TRUE); + +- insert_stylesheet (theme, file, stylesheet); + cr_stylesheet_ref (stylesheet); + theme->custom_stylesheets = g_slist_prepend (theme->custom_stylesheets, stylesheet); + g_signal_emit (theme, signals[STYLESHEETS_CHANGED], 0); +@@ -890,6 +910,7 @@ add_matched_properties (StTheme *a_this, + + if (import_rule->sheet == NULL) + { ++ CRStyleSheet *sheet = NULL; + GFile *file = NULL; + + if (import_rule->url->stryng && import_rule->url->stryng->str) +@@ -897,13 +918,12 @@ add_matched_properties (StTheme *a_this, + file = _st_theme_resolve_url (a_this, + a_nodesheet, + import_rule->url->stryng->str); +- import_rule->sheet = parse_stylesheet (file, NULL); ++ sheet = resolve_stylesheet (a_this, file, NULL); + } + +- if (import_rule->sheet) ++ if (sheet) + { +- insert_stylesheet (a_this, file, import_rule->sheet); +- /* refcount of stylesheets starts off at zero, so we don't need to unref! */ ++ import_rule->sheet = sheet; + } + else + { +-- +2.49.0 + diff --git a/SOURCES/0001-systemActions-Optionally-allow-restart-shutdown-on-l.patch b/SOURCES/0001-systemActions-Optionally-allow-restart-shutdown-on-l.patch new file mode 100644 index 0000000..28bc53a --- /dev/null +++ b/SOURCES/0001-systemActions-Optionally-allow-restart-shutdown-on-l.patch @@ -0,0 +1,63 @@ +From 193b664c7daa2ea7707e8b7fba03afe07e2cbd2a Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Tue, 15 Jul 2025 11:27:01 +0200 +Subject: [PATCH] systemActions: Optionally allow restart/shutdown on lock + screen + +Support the new 'restart-enabled' setting from 'org.gnome.desktop.screensaver' +to optionally allow restart/shutdown from the lock screen. + +Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/1584 +Part-of: +--- + js/misc/systemActions.js | 9 ++++++++- + 1 file changed, 8 insertions(+), 1 deletion(-) + +diff --git a/js/misc/systemActions.js b/js/misc/systemActions.js +index 10cab9a..9d3e09c 100644 +--- a/js/misc/systemActions.js ++++ b/js/misc/systemActions.js +@@ -7,10 +7,12 @@ const Main = imports.ui.main; + + const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown'; + const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; ++const SCREENSAVER_SCHEMA = 'org.gnome.desktop.screensaver'; + const DISABLE_USER_SWITCH_KEY = 'disable-user-switching'; + const DISABLE_LOCK_SCREEN_KEY = 'disable-lock-screen'; + const DISABLE_LOG_OUT_KEY = 'disable-log-out'; + const DISABLE_RESTART_KEY = 'disable-restart-buttons'; ++const RESTART_ENABLED_KEY = 'restart-enabled'; + const ALWAYS_SHOW_LOG_OUT_KEY = 'always-show-log-out'; + + const POWER_OFF_ACTION_ID = 'power-off'; +@@ -136,6 +138,7 @@ const SystemActions = GObject.registerClass({ + this._loginScreenSettings = new Gio.Settings({ schema_id: LOGIN_SCREEN_SCHEMA }); + this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA }); + this._orientationSettings = new Gio.Settings({ schema_id: 'org.gnome.settings-daemon.peripherals.touchscreen' }); ++ this._screenSaverSettings = new Gio.Settings({schema_id: SCREENSAVER_SCHEMA}); + + this._session = new GnomeSession.SessionManager(); + this._loginManager = LoginManager.getLoginManager(); +@@ -165,6 +168,9 @@ const SystemActions = GObject.registerClass({ + this._lockdownSettings.connect('changed::%s'.format(DISABLE_LOG_OUT_KEY), + () => this._updateHaveShutdown()); + ++ this._screenSaverSettings.connect(`changed::${RESTART_ENABLED_KEY}`, ++ () => this._updateHaveShutdown()); ++ + this.forceUpdate(); + + this._orientationSettings.connect('changed::orientation-lock', () => { +@@ -327,7 +333,8 @@ const SystemActions = GObject.registerClass({ + } + + _updatePowerOff() { +- let disabled = Main.sessionMode.isLocked || ++ let disabled = (Main.sessionMode.isLocked && ++ !this._screenSaverSettings.get_boolean(RESTART_ENABLED_KEY)) || + (Main.sessionMode.isGreeter && + this._loginScreenSettings.get_boolean(DISABLE_RESTART_KEY)); + this._actions.get(POWER_OFF_ACTION_ID).available = this._canHavePowerOff && !disabled; +-- +2.49.0 + diff --git a/SPECS/gnome-shell.spec b/SPECS/gnome-shell.spec index e820733..771a02a 100644 --- a/SPECS/gnome-shell.spec +++ b/SPECS/gnome-shell.spec @@ -8,7 +8,7 @@ Name: gnome-shell Version: 40.10 -Release: 24%{?dist} +Release: 28%{?dist} Summary: Window management and application launching for GNOME License: GPLv2+ @@ -35,6 +35,7 @@ Patch16: login-screen-extensions.patch Patch17: fix-resetting-auth-prompt.patch Patch18: 0001-authPrompt-Disregard-smartcard-status-changes-events.patch Patch19: 0001-loginDialog-Show-session-menu-button-when-in-IN_PROG.patch +Patch20: 0001-systemActions-Optionally-allow-restart-shutdown-on-l.patch # Misc. Patch30: 0001-panel-add-an-icon-to-the-ActivitiesButton.patch @@ -72,6 +73,8 @@ Patch61: screencast-bus-name.patch Patch62: fix-inhibit-shortcut-permission.patch Patch63: 0001-shell-window-tracker-Help-mutter-finding-app-info-s-.patch Patch64: 0001-dnd-Don-t-leak-a-signal-connection.patch +Patch65: 0001-st-theme-Reuse-stylesheets-if-possible.patch +Patch66: 0001-Support-conflicting-session-dialog.patch %define eds_version 3.33.1 %define gnome_desktop_version 3.35.91 @@ -301,6 +304,23 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de %endif %changelog +* Wed Jul 16 2025 Joan Torres - 40.10-28 +- Allow restart/shutdown on lock screen + Resolves: RHEL-103984 + +* Thu Jun 19 2025 Joan Torres - 40.10-27 +- session-opened signature is reverted to keep ABI compatibility, + use session-opened-with-session-id instead + Related: RHEL-92307 + +* Fri May 09 2025 Joan Torres - 40.10-26 +- Support conflicting session dialog + Resolves: RHEL-92307 + +* Mon May 05 2025 Florian Müllner - 40.10-25 +- Fix refount issue in stylesheet tracking + Resolves: RHEL-69401 + * Thu Feb 13 2025 Florian Müllner - 40.10-24 - Fix session button visibility after auth failure Resolves: RHEL-4116