import gnome-shell-3.32.2-40.el8

This commit is contained in:
CentOS Sources 2021-11-09 05:02:04 -05:00 committed by Stepan Oksanichenko
parent 7f32e65a87
commit aa3460ce67
17 changed files with 2162 additions and 15 deletions

View File

@ -1,7 +1,7 @@
From f03c6a870820543901331d1920b7b3e423813d2c Mon Sep 17 00:00:00 2001
From 6e80934456f0b4cc48da6a7201700dc4386a3474 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()
Subject: [PATCH] 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
@ -19,12 +19,12 @@ Signed-off-by: Christian Hergert <chergert@redhat.com>
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/js/ui/environment.js b/js/ui/environment.js
index e22ec7402..f3f2d17c7 100644
index 9c125d3eb..809b48e45 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 { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Gettext = imports.gettext;
+const System = imports.system;
+
@ -32,7 +32,7 @@ index e22ec7402..f3f2d17c7 100644
// 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() {
@@ -117,9 +120,26 @@ function init() {
}
};
@ -61,5 +61,5 @@ index e22ec7402..f3f2d17c7 100644
let slowdownEnv = GLib.getenv('GNOME_SHELL_SLOWDOWN_FACTOR');
--
2.26.2
2.31.1

View File

@ -0,0 +1,87 @@
From 1b6eb29ade832647510b36ddc13c9b88a25036df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Wed, 11 Sep 2019 20:18:20 +0200
Subject: [PATCH 1/4] extensionSystem: Handle added or removed sessionMode
extensions
Right now we're only handling added sessionMode extensions correctly on
sessionMode updates, also handle the other case and disable removed
sessionMode extensions on sessionMode updates.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/96
---
js/ui/extensionSystem.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 81804ea5e..77929f2a6 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -515,62 +515,62 @@ var ExtensionManager = class {
if (!this._initted) {
this._loadExtensions();
this._initted = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
this._enabled = true;
}
_disableAllExtensions() {
if (!this._enabled)
return;
if (this._initted) {
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) {
- if (this._initted)
- this._enabledExtensions = this._getEnabledExtensions();
+ // Take care of added or removed sessionMode extensions
+ this._onEnabledExtensionsChanged();
this._enableAllExtensions();
} else {
this._disableAllExtensions();
}
}
};
Signals.addSignalMethods(ExtensionManager.prototype);
class ExtensionUpdateSource extends MessageTray.Source {
constructor() {
const appSys = Shell.AppSystem.get_default();
this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop');
super(this._app.get_name());
}
getIcon() {
return this._app.app_info.get_icon();
}
_createPolicy() {
return new MessageTray.NotificationApplicationPolicy(this._app.id);
}
open() {
this._app.activate();
Main.overview.hide();
Main.panel.closeCalendar();
}
}
--
2.27.0

View File

@ -0,0 +1,91 @@
From e6cd96a9f6a89f77ca0fab72aff8c56354b59f38 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Aug 2019 15:01:34 -0400
Subject: [PATCH 1/4] shellEntry: Determine if password entry from content
purpose not menu item
Right now shellEntry decides whether or not it's a password entry based
on whether or not it has a "Show Text" context menu.
That's a little roundabout, and gets in the way off providing lockdown
that disables the menu.
This commit changes shellEntry to base whether or not it's a password
entry from it's input content purpose instead of from the presence
or absence of a context menu.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
---
js/ui/shellEntry.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index 53bd1daa1..cac4ec9c2 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -14,61 +14,61 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', this._onCopyActivated.bind(this));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', this._onPasteActivated.bind(this));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
}
_makePasswordItem() {
let item = new PopupMenu.PopupMenuItem('');
item.connect('activate', this._onPasswordActivated.bind(this));
this.addMenuItem(item);
this._passwordItem = item;
}
get isPassword() {
- return this._passwordItem != null;
+ return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
}
set isPassword(v) {
if (v == this.isPassword)
return;
if (v) {
this._makePasswordItem();
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
} else {
this._passwordItem.destroy();
this._passwordItem = null;
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
}
}
open(animate) {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
super.open(animate);
this._entry.add_style_pseudo_class('focus');
let direction = St.DirectionType.TAB_FORWARD;
if (!this.actor.navigate_focus(null, direction, false))
this.actor.grab_key_focus();
}
--
2.27.0

View File

@ -0,0 +1,36 @@
From fd8c4dc073b121b1093d68472cac3292d2c6605c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 14 Jun 2021 17:59:39 +0200
Subject: [PATCH] shellEntry: Disconnect handler on destroy
Actors will get unmapped on destroy, so unless we disconnect from
the notify::mapped signal, the handler will run one last time and
try to access methods/properties on the invalidated actor.
---
js/ui/shellEntry.js | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index 4a30b22f7..53bd1daa1 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -186,7 +186,7 @@ class CapsLockWarning extends St.Label {
this._keymap = Clutter.get_default_backend().get_keymap();
this._stateChangedId = 0;
- this.connect('notify::mapped', () => {
+ const mappedId = this.connect('notify::mapped', () => {
if (this.is_mapped()) {
this._stateChangedId = this._keymap.connect('state-changed',
() => this._sync(true));
@@ -201,6 +201,7 @@ class CapsLockWarning extends St.Label {
this.connect('destroy', () => {
if (this._stateChangedId)
this._keymap.disconnect(this._stateChangedId);
+ this.disconnect(mappedId);
});
}
--
2.31.1

View File

@ -0,0 +1,76 @@
From c68fd3c94c6debdbf11020940c5a6aaee8bc230d Mon Sep 17 00:00:00 2001
From: Feichtmeier <frederik.feichtmeier@gmail.com>
Date: Fri, 15 Mar 2019 14:41:55 +0100
Subject: [PATCH] theme: Update window preview style
- simplify the close button to use blue, lighter blue and darker blue
solid disks for normal, hover and active states
- use a milky, transparent white border for the hover effect of the border
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/461
---
data/theme/gnome-shell-sass/_common.scss | 29 ++++++++++++------------
1 file changed, 14 insertions(+), 15 deletions(-)
diff --git a/data/theme/gnome-shell-sass/_common.scss b/data/theme/gnome-shell-sass/_common.scss
index 9e0751c8c..8bf368f6e 100644
--- a/data/theme/gnome-shell-sass/_common.scss
+++ b/data/theme/gnome-shell-sass/_common.scss
@@ -1164,25 +1164,23 @@ StScrollBar {
//close buttons
.window-close {
- background-color: white;
+ background-color: $selected_bg_color;
+ color: white;
border-radius: 24px;
- border: 4px solid $selected_bg_color;
- box-shadow: inset 0 -4px 0 0 transparentize($selected_bg_color, 0.5);
- color: $selected_bg_color;
+ border: 2px solid $selected_bg_color;
height: 24px;
width: 24px;
- -shell-close-overlap: 14px;
+ -shell-close-overlap: 11px;
+ box-shadow: -1px 1px 5px 0px transparentize(black, 0.5);
&:hover {
- background-color: $selected_bg_color;
- border-color: white;
- color: white;
+ background-color: lighten($selected_bg_color, 5%);
+ border-color: lighten($selected_bg_color, 5%);
}
&:active {
- background-color: mix(white, $selected_bg_color, 75%);
- border-color: $selected_bg_color;
- color: $selected_bg_color;
+ background-color: darken($selected_bg_color, 5%);
+ border-color: darken($selected_bg_color, 5%);
}
}
@@ -1247,13 +1245,14 @@ StScrollBar {
}
.window-clone-border {
- border: 4px solid $selected_bg_color;
- border-radius: 4px;
+ $_bg: transparentize(white, 0.65);
+ border: 5px solid $_bg;
+ border-radius: 6px;
// For window decorations with round corners we can't match
// the exact shape when the window is scaled. So apply a shadow
// to fix that case
- box-shadow: inset 0px 0px 0px 1px $selected_bg_color;
- }
+ box-shadow: inset 0 0 0 1px $_bg;
+}
.window-caption {
spacing: 25px;
color: $selected_fg_color;
--
2.31.1

View File

@ -0,0 +1,237 @@
From b70cf463e08bff43b242b851fc7c79244f54e76b Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Aug 2021 13:25:57 -0400
Subject: [PATCH 2/4] 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 | 13 -------------
1 file changed, 13 deletions(-)
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 77929f2a6..05630ed54 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -1,53 +1,52 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { GLib, Gio, GObject, St } = imports.gi;
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 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._initted = false;
- this._enabled = false;
this._updateNotified = false;
this._extensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
}
init() {
this._installExtensionUpdates();
this._sessionUpdated();
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => {
ExtensionDownloader.checkForUpdates();
return GLib.SOURCE_CONTINUE;
});
ExtensionDownloader.checkForUpdates();
}
lookup(uuid) {
return this._extensions.get(uuid);
}
getUuids() {
return [...this._extensions.keys()];
}
_callExtensionDisable(uuid) {
let extension = this.lookup(uuid);
@@ -375,63 +374,60 @@ var ExtensionManager = class {
let hasError =
extension.state == ExtensionState.ERROR ||
extension.state == ExtensionState.OUT_OF_DATE;
let isMode = this._getModeExtensions().includes(extension.uuid);
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
extension.canChange =
!hasError &&
global.settings.is_writable(ENABLED_EXTENSIONS_KEY) &&
(isMode || !modeOnly);
}
_getEnabledExtensions() {
let extensions = this._getModeExtensions();
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
return extensions;
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
}
_onUserExtensionsEnabledChanged() {
this._onEnabledExtensionsChanged();
this._onSettingsWritableChanged();
}
_onEnabledExtensionsChanged() {
let newEnabledExtensions = this._getEnabledExtensions();
- if (!this._enabled)
- return;
-
// 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)
).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._enabledExtensions.filter(
item => !newEnabledExtensions.includes(item)
).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() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
@@ -482,85 +478,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 ${uuid} already installed in ${existing.path}. ${dir.get_path()} will not be loaded`);
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 ${uuid}`);
return;
}
this.loadExtension(extension);
});
}
_enableAllExtensions() {
- if (this._enabled)
- return;
-
if (!this._initted) {
this._loadExtensions();
this._initted = true;
} else {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
}
- this._enabled = true;
}
_disableAllExtensions() {
- if (!this._enabled)
- return;
-
if (this._initted) {
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);
class ExtensionUpdateSource extends MessageTray.Source {
constructor() {
const appSys = Shell.AppSystem.get_default();
this._app = appSys.lookup_app('gnome-shell-extension-prefs.desktop');
super(this._app.get_name());
}
getIcon() {
return this._app.app_info.get_icon();
}
--
2.27.0

View File

@ -0,0 +1,92 @@
From de7df6c7248c39d7cce1c70485df72a398da92a3 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Aug 2019 15:48:33 -0400
Subject: [PATCH 2/4] shellEntry: Give password menu item text when it's
created
At the moment, the "Show Text" menu item is only given its text
at the time the menu is opened. This is because the text might
be "Hide Text" or "Show Text" depending on state, so the text
is set up lazily.
That behavior means the menu item can't get added after the
menu is already shown, which is something we'ree going to need
in the future to support lockdown of the "Show Text" item.
This commit ensures the menu item is given text when it's first
created, in addition to when the menu is opened.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
---
js/ui/shellEntry.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index cac4ec9c2..603a9c64a 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -11,60 +11,61 @@ const Tweener = imports.ui.tweener;
var EntryMenu = class extends PopupMenu.PopupMenu {
constructor(entry) {
super(entry, 0, St.Side.TOP);
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', this._onCopyActivated.bind(this));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', this._onPasteActivated.bind(this));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
}
_makePasswordItem() {
let item = new PopupMenu.PopupMenuItem('');
item.connect('activate', this._onPasswordActivated.bind(this));
this.addMenuItem(item);
this._passwordItem = item;
+ this._updatePasswordItem();
}
get isPassword() {
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
}
set isPassword(v) {
if (v == this.isPassword)
return;
if (v) {
this._makePasswordItem();
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
} else {
this._passwordItem.destroy();
this._passwordItem = null;
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
}
}
open(animate) {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
super.open(animate);
this._entry.add_style_pseudo_class('focus');
let direction = St.DirectionType.TAB_FORWARD;
--
2.27.0

View File

@ -0,0 +1,393 @@
From 7300ae2eac743fa06f40f6459ac8fbf739ab28ea Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Aug 2021 15:03:50 -0400
Subject: [PATCH 3/4] 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 | 43 ++++++++++++++++++++++++++++++++++++----
1 file changed, 39 insertions(+), 4 deletions(-)
diff --git a/js/ui/extensionSystem.js b/js/ui/extensionSystem.js
index 05630ed54..dfe82821e 100644
--- a/js/ui/extensionSystem.js
+++ b/js/ui/extensionSystem.js
@@ -21,119 +21,147 @@ var ExtensionManager = class {
constructor() {
this._initted = false;
this._updateNotified = false;
this._extensions = new Map();
this._enabledExtensions = [];
this._extensionOrder = [];
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
}
init() {
this._installExtensionUpdates();
this._sessionUpdated();
GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, UPDATE_CHECK_TIMEOUT, () => {
ExtensionDownloader.checkForUpdates();
return GLib.SOURCE_CONTINUE;
});
ExtensionDownloader.checkForUpdates();
}
lookup(uuid) {
return this._extensions.get(uuid);
}
getUuids() {
return [...this._extensions.keys()];
}
+ _extensionSupportsSessionMode(uuid) {
+ let 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 uuid = orderReversed[i];
try {
this.lookup(uuid).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;
}
try {
extension.stateObj.disable();
} catch(e) {
this.logExtensionError(uuid, e);
}
for (let i = 0; i < order.length; i++) {
let uuid = order[i];
try {
this.lookup(uuid).stateObj.enable();
} catch (e) {
this.logExtensionError(uuid, e);
}
}
this._extensionOrder.splice(orderIdx, 1);
if (extension.state != ExtensionState.ERROR) {
extension.state = ExtensionState.DISABLED;
this.emit('extension-state-changed', extension);
}
}
_callExtensionEnable(uuid) {
+ 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;
this._extensionOrder.push(uuid);
let stylesheetNames = [global.session_mode + '.css', '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
log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
return;
}
}
try {
extension.stateObj.enable();
@@ -231,61 +259,62 @@ var ExtensionManager = class {
throw new Error(`Failed to load metadata.json: ${e}`);
}
let meta;
try {
meta = JSON.parse(metadataContents);
} catch (e) {
throw new Error(`Failed to parse metadata.json: ${e}`);
}
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 "${prop}" property in metadata.json`);
}
}
if (uuid != meta.uuid) {
throw new Error(`uuid "${meta.uuid}" from metadata.json does not match directory name "${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
+ canChange: false,
+ sessionModes: meta['session-modes'] ? meta['session-modes'] : [ 'user' ],
};
this._extensions.set(uuid, extension);
return extension;
}
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 {
let enabled = this._enabledExtensions.includes(extension.uuid);
if (enabled) {
if (!this._callExtensionInit(extension.uuid))
return;
if (extension.state == ExtensionState.DISABLED)
this._callExtensionEnable(extension.uuid);
} else {
extension.state = ExtensionState.INITIALIZED;
}
}
this._updateCanChange(extension);
this.emit('extension-state-changed', extension);
}
@@ -296,60 +325,63 @@ var ExtensionManager = class {
this._callExtensionDisable(extension.uuid);
extension.state = ExtensionState.UNINSTALLED;
this.emit('extension-state-changed', extension);
this._extensions.delete(extension.uuid);
return true;
}
reloadExtension(oldExtension) {
// Grab the things we'll need to pass to createExtensionObject
// to reload it.
let { uuid: uuid, dir: dir, type: 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 (!this._sessionModeCanUseExtension(uuid))
+ return false;
+
let extension = this.lookup(uuid);
let dir = extension.dir;
if (!extension)
throw new Error("Extension was not properly created. Call loadExtension first");
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;
}
@@ -377,69 +409,72 @@ var ExtensionManager = class {
let isMode = this._getModeExtensions().includes(extension.uuid);
let modeOnly = global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY);
extension.canChange =
!hasError &&
global.settings.is_writable(ENABLED_EXTENSIONS_KEY) &&
(isMode || !modeOnly);
}
_getEnabledExtensions() {
let extensions = this._getModeExtensions();
if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
return extensions;
return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
}
_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)
+ 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.
+ // old setting, but not in the new one, and extensions that don't work with
+ // the current session mode.
this._enabledExtensions.filter(
- item => !newEnabledExtensions.includes(item)
+ item => !newEnabledExtensions.includes(item) ||
+ !this._extensionSupportsSessionMode(item)
).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() {
// we want to reload all extensions, but only enable
// extensions when allowed by the sessionMode, so
// temporarily disable them all
this._enabledExtensions = [];
// The loop modifies the extensions map, so iterate over a copy
let extensions = [...this._extensions.values()];
for (let extension of extensions)
this.reloadExtension(extension);
this._enabledExtensions = this._getEnabledExtensions();
if (Main.sessionMode.allowExtensions) {
this._enabledExtensions.forEach(uuid => {
this._callExtensionEnable(uuid);
});
--
2.27.0

View File

@ -0,0 +1,119 @@
From 39cf97176e2a92506081ee151ea546e2c6cf213a Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Aug 2019 15:06:46 -0400
Subject: [PATCH 3/4] shellEntry: Handle password item from dedication function
At the moment, shellEntry handles creating and destroying its
"Show Text" password menu item directly from its isPassword
setter function.
This commit moves that handling to a dedicated _resetPasswordItem
function, as prep work for adding lockdown support of the "Show Text"
menu item.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
---
js/ui/shellEntry.js | 23 +++++++++++++++++------
1 file changed, 17 insertions(+), 6 deletions(-)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index 603a9c64a..765cede06 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -14,76 +14,87 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', this._onCopyActivated.bind(this));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', this._onPasteActivated.bind(this));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
}
_makePasswordItem() {
let item = new PopupMenu.PopupMenuItem('');
item.connect('activate', this._onPasswordActivated.bind(this));
this.addMenuItem(item);
this._passwordItem = item;
this._updatePasswordItem();
}
+ _resetPasswordItem() {
+ if (!this.isPassword) {
+ if (this._passwordItem) {
+ this._passwordItem.destroy();
+ this._passwordItem = null;
+ }
+ this._entry.clutter_text.set_password_char('\u25cf');
+ } else {
+ if (!this._passwordItem)
+ this._makePasswordItem();
+ }
+ }
+
get isPassword() {
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
}
set isPassword(v) {
if (v == this.isPassword)
return;
- if (v) {
- this._makePasswordItem();
+ if (v)
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
- } else {
- this._passwordItem.destroy();
- this._passwordItem = null;
+ else
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
- }
+
+ this._resetPasswordItem();
}
open(animate) {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
super.open(animate);
this._entry.add_style_pseudo_class('focus');
let direction = St.DirectionType.TAB_FORWARD;
if (!this.actor.navigate_focus(null, direction, false))
this.actor.grab_key_focus();
}
_updateCopyItem() {
let selection = this._entry.clutter_text.get_selection();
this._copyItem.setSensitive(!this._entry.clutter_text.password_char &&
selection && selection != '');
}
_updatePasteItem() {
this._clipboard.get_text(St.ClipboardType.CLIPBOARD,
(clipboard, text) => {
this._pasteItem.setSensitive(text && text != '');
});
}
_updatePasswordItem() {
--
2.27.0

View File

@ -0,0 +1,116 @@
From 5fad989ca773f9e0ff6fdbeb0cb7c9cb70cc6148 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Tue, 10 Aug 2021 15:31:00 -0400
Subject: [PATCH 4/4] 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 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index fa7f83416..8d8ce1a64 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -12,89 +12,92 @@ const Config = imports.misc.config;
const DEFAULT_MODE = 'restrictive';
const _modes = {
'restrictive': {
parentMode: null,
stylesheetName: 'gnome-shell.css',
hasOverview: false,
showCalendarEvents: false,
allowSettings: false,
allowExtensions: false,
allowScreencast: false,
enabledExtensions: [],
hasRunDialog: false,
hasWorkspaces: false,
hasWindows: false,
hasNotifications: 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: ['a11y', 'keyboard', 'aggregateMenu']
},
panelStyle: 'login-screen'
},
'lock-screen': {
+ allowExtensions: true,
isLocked: true,
isGreeter: undefined,
unlockDialog: undefined,
components: ['polkitAgent', 'telepathyClient'],
panel: {
left: [],
center: [],
right: ['aggregateMenu']
},
panelStyle: 'lock-screen'
},
'unlock-dialog': {
+ allowExtensions: true,
isLocked: true,
unlockDialog: undefined,
components: ['polkitAgent', 'telepathyClient'],
panel: {
left: [],
center: [],
right: ['a11y', 'keyboard', 'aggregateMenu']
},
panelStyle: 'unlock-screen'
},
'user': {
hasOverview: true,
showCalendarEvents: true,
allowSettings: true,
allowExtensions: true,
allowScreencast: true,
hasRunDialog: true,
hasWorkspaces: true,
hasWindows: true,
hasNotifications: true,
isLocked: false,
isPrimary: true,
unlockDialog: imports.ui.unlockDialog.UnlockDialog,
components: Config.HAVE_NETWORKMANAGER ?
['networkAgent', 'polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'] :
['polkitAgent', 'telepathyClient',
'keyring', 'autorunManager', 'automountManager'],
--
2.27.0

View File

@ -0,0 +1,116 @@
From ee64cd773bdeef845d02dc84063f926d77090dec Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 21 Aug 2019 15:06:46 -0400
Subject: [PATCH 4/4] shellEntry: Support lockdown of "Show Text" menu in
password entries
Some deployments require being able to prevent users from showing
the password they're currently typing.
This commit adds support for that kind of lockdown.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/687
---
js/ui/shellEntry.js | 14 +++++++++++---
1 file changed, 11 insertions(+), 3 deletions(-)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index 765cede06..c45e4545a 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -1,81 +1,89 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const { Clutter, GObject, Pango, Shell, St } = imports.gi;
+const { Clutter, Gio, GObject, Pango, Shell, St } = imports.gi;
const BoxPointer = imports.ui.boxpointer;
const Main = imports.ui.main;
const Params = imports.misc.params;
const PopupMenu = imports.ui.popupMenu;
const Tweener = imports.ui.tweener;
+const LOCKDOWN_SCHEMA = 'org.gnome.desktop.lockdown';
+const DISABLE_SHOW_PASSWORD_KEY = 'disable-show-password';
+
var EntryMenu = class extends PopupMenu.PopupMenu {
constructor(entry) {
super(entry, 0, St.Side.TOP);
+ this._lockdownSettings = new Gio.Settings({ schema_id: LOCKDOWN_SCHEMA });
+ this._lockdownSettings.connect('changed::' + DISABLE_SHOW_PASSWORD_KEY, this._resetPasswordItem.bind(this));
+
this._entry = entry;
this._clipboard = St.Clipboard.get_default();
// Populate menu
let item;
item = new PopupMenu.PopupMenuItem(_("Copy"));
item.connect('activate', this._onCopyActivated.bind(this));
this.addMenuItem(item);
this._copyItem = item;
item = new PopupMenu.PopupMenuItem(_("Paste"));
item.connect('activate', this._onPasteActivated.bind(this));
this.addMenuItem(item);
this._pasteItem = item;
this._passwordItem = null;
Main.uiGroup.add_actor(this.actor);
this.actor.hide();
}
_makePasswordItem() {
let item = new PopupMenu.PopupMenuItem('');
item.connect('activate', this._onPasswordActivated.bind(this));
this.addMenuItem(item);
this._passwordItem = item;
this._updatePasswordItem();
}
_resetPasswordItem() {
- if (!this.isPassword) {
+ let passwordDisabled = this._lockdownSettings.get_boolean(DISABLE_SHOW_PASSWORD_KEY);
+
+ if (!this.isPassword || passwordDisabled) {
if (this._passwordItem) {
this._passwordItem.destroy();
this._passwordItem = null;
}
this._entry.clutter_text.set_password_char('\u25cf');
- } else {
+ } else if (this.isPassword && !passwordDisabled) {
if (!this._passwordItem)
this._makePasswordItem();
}
}
get isPassword() {
return this._entry.input_purpose == Clutter.InputContentPurpose.PASSWORD;
}
set isPassword(v) {
if (v == this.isPassword)
return;
if (v)
this._entry.input_purpose = Clutter.InputContentPurpose.PASSWORD;
else
this._entry.input_purpose = Clutter.InputContentPurpose.NORMAL;
this._resetPasswordItem();
}
open(animate) {
this._updatePasteItem();
this._updateCopyItem();
if (this._passwordItem)
this._updatePasswordItem();
super.open(animate);
this._entry.add_style_pseudo_class('focus');
--
2.27.0

View File

@ -0,0 +1,36 @@
From 7a264550c5f3a98b1786b1a75cff01cde1d084eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 29 Jul 2021 17:17:43 +0200
Subject: [PATCH 5/5] shellEntry: Only mask text in password entries
When "Show Text" is locked down, we not only remove the corresponding
menu item, but also make sure the password is masked.
Except that the current code is too eager, and masks the text in
any entries.
---
js/ui/shellEntry.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/js/ui/shellEntry.js b/js/ui/shellEntry.js
index c45e4545a..64b389050 100644
--- a/js/ui/shellEntry.js
+++ b/js/ui/shellEntry.js
@@ -55,11 +55,13 @@ var EntryMenu = class extends PopupMenu.PopupMenu {
this._passwordItem.destroy();
this._passwordItem = null;
}
- this._entry.clutter_text.set_password_char('\u25cf');
} else if (this.isPassword && !passwordDisabled) {
if (!this._passwordItem)
this._makePasswordItem();
}
+
+ if (this.isPassword && passwordDisabled)
+ this._entry.clutter_text.set_password_char('\u25cf');
}
get isPassword() {
--
2.31.1

View File

@ -3808,4 +3808,3 @@ index 0bd77e125..1e6f5340a 100644
--
2.29.2

View File

@ -0,0 +1,161 @@
From 214c4f390faa40199c03a80594313760ffe9c5a6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 20 Sep 2019 13:17:40 +0200
Subject: [PATCH 1/2] unlockDialog: Use inheritance instead of composition
The screen shield creates the unlock dialog based on the session mode.
However since commit 0c0d76f7d6990 turned LoginDialog into an actor
subclass (while UnlockDialog kept using the delegate pattern), it is
no longer possible to handle both objects the same way without warnings.
Allow this again by turning UnlockDialog into an actor subclass as well.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
---
js/ui/unlockDialog.js | 46 ++++++++++++++++++++++++-------------------
1 file changed, 26 insertions(+), 20 deletions(-)
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index 4b0470f4b..55abb652d 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -1,8 +1,7 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
const { AccountsService, Atk, Clutter,
- Gdm, Gio, GLib, Meta, Shell, St } = imports.gi;
-const Signals = imports.signals;
+ Gdm, Gio, GLib, GObject, Meta, Shell, St } = imports.gi;
const Layout = imports.ui.layout;
const Main = imports.ui.main;
@@ -12,15 +11,19 @@ const AuthPrompt = imports.gdm.authPrompt;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
-var UnlockDialog = class {
- constructor(parentActor) {
- this.actor = new St.Widget({ accessible_role: Atk.Role.WINDOW,
- style_class: 'login-dialog',
- layout_manager: new Clutter.BoxLayout(),
- visible: false });
+var UnlockDialog = GObject.registerClass({
+ Signals: { 'failed': {} },
+}, class UnlockDialog extends St.Widget {
+ _init(parentActor) {
+ super._init({
+ accessible_role: Atk.Role.WINDOW,
+ style_class: 'login-dialog',
+ layout_manager: new Clutter.BoxLayout(),
+ visible: false,
+ });
- this.actor.add_constraint(new Layout.MonitorConstraint({ primary: true }));
- parentActor.add_child(this.actor);
+ this.add_constraint(new Layout.MonitorConstraint({ primary: true }));
+ parentActor.add_child(this);
this._userManager = AccountsService.UserManager.get_default();
this._userName = GLib.get_user_name();
@@ -31,7 +34,7 @@ var UnlockDialog = class {
y_align: Clutter.ActorAlign.CENTER,
x_expand: true,
y_expand: true });
- this.actor.add_child(this._promptBox);
+ this.add_child(this._promptBox);
this._gdmClient = new Gdm.Client();
@@ -70,10 +73,12 @@ var UnlockDialog = class {
this._authPrompt.reset();
this._updateSensitivity(true);
- Main.ctrlAltTabManager.addGroup(this.actor, _("Unlock Window"), 'dialog-password-symbolic');
+ Main.ctrlAltTabManager.addGroup(this, _("Unlock Window"), 'dialog-password-symbolic');
this._idleMonitor = Meta.IdleMonitor.get_core();
this._idleWatchId = this._idleMonitor.add_idle_watch(IDLE_TIMEOUT * 1000, this._escape.bind(this));
+
+ this.connect('destroy', this._onDestroy.bind(this));
}
_updateSensitivity(sensitive) {
@@ -112,9 +117,8 @@ var UnlockDialog = class {
this._authPrompt.cancel();
}
- destroy() {
+ _onDestroy() {
this.popModal();
- this.actor.destroy();
if (this._idleWatchId) {
this._idleMonitor.remove_watch(this._idleWatchId);
@@ -137,13 +141,16 @@ var UnlockDialog = class {
}
open(timestamp) {
- this.actor.show();
+ this.show();
if (this._isModal)
return true;
- if (!Main.pushModal(this.actor, { timestamp: timestamp,
- actionMode: Shell.ActionMode.UNLOCK_SCREEN }))
+ let modalParams = {
+ timestamp,
+ actionMode: Shell.ActionMode.UNLOCK_SCREEN,
+ };
+ if (!Main.pushModal(this, modalParams))
return false;
this._isModal = true;
@@ -153,9 +160,8 @@ var UnlockDialog = class {
popModal(timestamp) {
if (this._isModal) {
- Main.popModal(this.actor, timestamp);
+ Main.popModal(this, timestamp);
this._isModal = false;
}
}
-};
-Signals.addSignalMethods(UnlockDialog.prototype);
+});
--
2.31.1
From cddeb2f4e38928e0d5e0f3a852961f639536aff3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 20 Sep 2019 13:14:40 +0200
Subject: [PATCH 2/2] screenShield: Stop using deprecated actor property
Both LoginDialog and UnlockDialog are now actor subclasses, so stop
using the deprecated actor delegate that will trigger a warning.
https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/736
---
js/ui/screenShield.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 2d0a429be..f97a9288a 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -917,8 +917,8 @@ var ScreenShield = class {
this._lockScreenGroup.hide();
if (this._dialog) {
- this._dialog.actor.grab_key_focus();
- this._dialog.actor.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
+ this._dialog.grab_key_focus();
+ this._dialog.navigate_focus(null, St.DirectionType.TAB_FORWARD, false);
}
}
--
2.31.1

View File

@ -0,0 +1,246 @@
From ed0699886f49e5dd8d6ca9ffb60ba17cd76a810f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 7 Jun 2021 17:49:57 +0200
Subject: [PATCH 1/5] status/network: Disable modem connection when windows
aren't allowed
The item launches the corresponding Settings panel when activated, which
doesn't work when windows are disabled by the session mode. Rather than
failing silently, turn the item insensitive.
---
js/ui/status/network.js | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index b3bb7589c..3ad7b04dd 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -514,6 +514,10 @@ var NMDeviceModem = class extends NMConnectionDevice {
this._iconChanged();
});
}
+
+ this._sessionUpdatedId =
+ Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+ this._sessionUpdated();
}
get category() {
@@ -525,6 +529,10 @@ var NMDeviceModem = class extends NMConnectionDevice {
'connect-3g', this._device.get_path()]);
}
+ _sessionUpdated() {
+ this._autoConnectItem.sensitive = Main.sessionMode.hasWindows;
+ }
+
destroy() {
if (this._operatorNameId) {
this._mobileDevice.disconnect(this._operatorNameId);
@@ -534,6 +542,10 @@ var NMDeviceModem = class extends NMConnectionDevice {
this._mobileDevice.disconnect(this._signalQualityId);
this._signalQualityId = 0;
}
+ if (this._sessionUpdatedId) {
+ Main.sessionMode.disconnect(this._sessionUpdatedId);
+ this._sessionUpdatedId = 0;
+ }
super.destroy();
}
--
2.31.1
From 59d52e1591e1522fff22320c657496ca978a7926 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 7 Jun 2021 18:28:32 +0200
Subject: [PATCH 2/5] status/network: Only list wifi networks that can be
activated
Setting up a connection for an Enterprise WPA(2) encrypted wireless
network requires Settings. That's not available when windows are
disabled via the session mode, so filter out affected entries.
---
js/ui/status/network.js | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 3ad7b04dd..c023022a7 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const { Clutter, Gio, GLib, GObject, NM, St } = imports.gi;
+const { Clutter, Gio, GLib, GObject, Meta, NM, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
@@ -751,6 +751,11 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
this._scanTimeoutId = 0;
}
+ if (this._syncVisibilityId) {
+ Meta.later_remove(this._syncVisibilityId);
+ this._syncVisibilityId = 0;
+ }
+
super.destroy();
}
@@ -1081,9 +1086,31 @@ var NMWirelessDialog = class extends ModalDialog.ModalDialog {
this._itemBox.insert_child_at_index(network.item.actor, newPos);
}
+ this._queueSyncItemVisibility();
this._syncView();
}
+ _queueSyncItemVisibility() {
+ if (this._syncVisibilityId)
+ return;
+
+ this._syncVisibilityId = Meta.later_add(
+ Meta.LaterType.BEFORE_REDRAW,
+ () => {
+ const { hasWindows } = Main.sessionMode;
+ const { WPA2_ENT, WPA_ENT } = NMAccessPointSecurity;
+
+ for (const network of this._networks) {
+ const [firstAp] = network.accessPoints;
+ network.item.visible =
+ hasWindows ||
+ network.connections.length > 0 ||
+ (firstAp._secType !== WPA2_ENT && firstAp._secType !== WPA_ENT);
+ }
+ return GLib.SOURCE_REMOVE;
+ });
+ }
+
_accessPointRemoved(device, accessPoint) {
let res = this._findExistingNetwork(accessPoint);
--
2.31.1
From 9d204cdb38bcfee214dbe0b0bf9c2073dc50fe93 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Tue, 8 Jun 2021 00:17:48 +0200
Subject: [PATCH 3/5] status/network: Consider network-control action
NetworkManager installs a `network-control` polkit action that can
be used to disallow network configuration, except that we happily
ignore it. Add it to the conditions that turn a network section
insensitive.
---
js/ui/status/network.js | 20 +++++++++++++++++---
1 file changed, 17 insertions(+), 3 deletions(-)
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index c023022a7..79729e01b 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -1,5 +1,5 @@
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
-const { Clutter, Gio, GLib, GObject, Meta, NM, St } = imports.gi;
+const { Clutter, Gio, GLib, GObject, Meta, NM, Polkit, St } = imports.gi;
const Mainloop = imports.mainloop;
const Signals = imports.signals;
@@ -1683,11 +1683,25 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
this._client.connect('connection-removed', this._connectionRemoved.bind(this));
Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
- this._sessionUpdated();
+
+ this._configPermission = null;
+ Polkit.Permission.new(
+ 'org.freedesktop.NetworkManager.network-control', null, null,
+ (o, res) => {
+ try {
+ this._configPermission = Polkit.Permission.new_finish(res);
+ } catch (e) {
+ log('No permission to control network connections: %s'.format(e.toString()));
+ }
+ this._sessionUpdated();
+ });
}
_sessionUpdated() {
- let sensitive = !Main.sessionMode.isLocked && !Main.sessionMode.isGreeter;
+ const sensitive =
+ !Main.sessionMode.isLocked &&
+ !Main.sessionMode.isGreeter &&
+ this._configPermission && this._configPermission.allowed;
this.menu.setSensitive(sensitive);
}
--
2.31.1
From 7d2c8aabb86b9942c99ae9b7157dbffb875acde9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 10 Jun 2021 23:12:27 +0200
Subject: [PATCH 4/5] sessionMode: Enable networkAgent on login screen
We will soon enable the network sections in the status menu on the
login screen, so enable the network agent to handle authentication
requests (like wifi/VPN passwords).
---
js/ui/sessionMode.js | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/js/ui/sessionMode.js b/js/ui/sessionMode.js
index 25aa75a3d..fa7f83416 100644
--- a/js/ui/sessionMode.js
+++ b/js/ui/sessionMode.js
@@ -43,7 +43,9 @@ const _modes = {
isGreeter: true,
isPrimary: true,
unlockDialog: imports.gdm.loginDialog.LoginDialog,
- components: ['polkitAgent'],
+ components: Config.HAVE_NETWORKMANAGER
+ ? ['networkAgent', 'polkitAgent']
+ : ['polkitAgent'],
panel: {
left: [],
center: ['dateMenu'],
--
2.31.1
From 07ce899bcb9d30991262d6c484508e6c5fa14c85 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Tue, 8 Jun 2021 00:19:26 +0200
Subject: [PATCH 5/5] status/network: Do not disable on login screen
We currently disable all network items on both the lock- and login
screen. While it makes sense to be very restrictive on the lock screen,
there are some (fringe) use cases for being more permissive on the
login screen (like remote home directories only accessible via VPN).
There's precedence with the power-off/restart actions to be less
restrictive on the login screen, and since we started respecting
the `network-control` polkit action, it's possible to restore the
old behavior if desired.
---
js/ui/status/network.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/js/ui/status/network.js b/js/ui/status/network.js
index 79729e01b..914dbbd99 100644
--- a/js/ui/status/network.js
+++ b/js/ui/status/network.js
@@ -1700,7 +1700,6 @@ var NMApplet = class extends PanelMenu.SystemIndicator {
_sessionUpdated() {
const sensitive =
!Main.sessionMode.isLocked &&
- !Main.sessionMode.isGreeter &&
this._configPermission && this._configPermission.allowed;
this.menu.setSensitive(sensitive);
}
--
2.31.1

279
SOURCES/warn-less.patch Normal file
View File

@ -0,0 +1,279 @@
From 37bbb9175bbd061d4ae14e86c35e4211602dbeaa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 23 Mar 2020 17:57:38 +0100
Subject: [PATCH 1/4] shell/util: Add touch_file_async() helper
Add a small helper method to asynchronously "touch" a file and return
whether the file was created or not.
As g_file_make_directory_with_parents() doesn't have an async variant,
we need a C helper to make the entire operation non-blocking.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432
---
src/shell-util.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++
src/shell-util.h | 7 ++++++
2 files changed, 69 insertions(+)
diff --git a/src/shell-util.c b/src/shell-util.c
index fa3fc08c8..eec67f3d7 100644
--- a/src/shell-util.c
+++ b/src/shell-util.c
@@ -323,6 +323,68 @@ shell_get_file_contents_utf8_sync (const char *path,
return contents;
}
+static void
+touch_file (GTask *task,
+ gpointer object,
+ gpointer task_data,
+ GCancellable *cancellable)
+{
+ GFile *file = object;
+ g_autoptr (GFile) parent = NULL;
+ g_autoptr (GFileOutputStream) stream = NULL;
+ GError *error = NULL;
+
+ parent = g_file_get_parent (file);
+ g_file_make_directory_with_parents (parent, cancellable, &error);
+
+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+ g_clear_error (&error);
+
+ stream = g_file_create (file, G_FILE_CREATE_NONE, cancellable, &error);
+
+ if (error && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_EXISTS))
+ {
+ g_task_return_error (task, error);
+ return;
+ }
+ g_clear_error (&error);
+
+ if (stream)
+ g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL);
+
+ g_task_return_boolean (task, stream != NULL);
+}
+
+void
+shell_util_touch_file_async (GFile *file,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_autoptr (GTask) task = NULL;
+
+ g_return_if_fail (G_IS_FILE (file));
+
+ task = g_task_new (file, NULL, callback, user_data);
+ g_task_set_source_tag (task, shell_util_touch_file_async);
+
+ g_task_run_in_thread (task, touch_file);
+}
+
+gboolean
+shell_util_touch_file_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error)
+{
+ g_return_val_if_fail (G_IS_FILE (file), FALSE);
+ g_return_val_if_fail (G_IS_TASK (res), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
/**
* shell_util_wifexited:
* @status: the status returned by wait() or waitpid()
diff --git a/src/shell-util.h b/src/shell-util.h
index 02b8404e9..bedf516ba 100644
--- a/src/shell-util.h
+++ b/src/shell-util.h
@@ -32,6 +32,13 @@ gboolean shell_write_string_to_stream (GOutputStream *stream,
char *shell_get_file_contents_utf8_sync (const char *path,
GError **error);
+void shell_util_touch_file_async (GFile *file,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean shell_util_touch_file_finish (GFile *file,
+ GAsyncResult *res,
+ GError **error);
+
gboolean shell_util_wifexited (int status,
int *exit);
--
2.31.1
From 1f75494bea1ef7017d50d77cf5c7ad6b9668d4f5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Mon, 23 Mar 2020 18:00:27 +0100
Subject: [PATCH 2/4] environment: Hook up touch_file to GFile prototype
We don't usually extend introspected types with our own API, but in
this case it's too tempting to make the helper functions usable with
Gio._promisify() ...
https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432
---
js/ui/environment.js | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/js/ui/environment.js b/js/ui/environment.js
index e22ec7402..9c125d3eb 100644
--- a/js/ui/environment.js
+++ b/js/ui/environment.js
@@ -9,7 +9,7 @@ imports.gi.versions.Gtk = '3.0';
imports.gi.versions.TelepathyGLib = '0.12';
imports.gi.versions.TelepathyLogger = '0.2';
-const { Clutter, GLib, Shell, St } = imports.gi;
+const { Clutter, Gio, GLib, Shell, St } = imports.gi;
const Gettext = imports.gettext;
// We can't import shell JS modules yet, because they may have
@@ -97,6 +97,13 @@ function init() {
return St.describe_actor(this);
};
+ Gio._LocalFilePrototype.touch_async = function (callback) {
+ Shell.util_touch_file_async(this, callback);
+ };
+ Gio._LocalFilePrototype.touch_finish = function (result) {
+ return Shell.util_touch_file_finish(this, result);
+ };
+
let origToString = Object.prototype.toString;
Object.prototype.toString = function() {
let base = origToString.call(this);
--
2.31.1
From 4bef23c7176a43f4dcf146e70bbb8aaa701b8cd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Fri, 20 Mar 2020 12:42:04 +0100
Subject: [PATCH 3/4] main: Do not warn about missing GDM on each login
We now warn on startup if screen locking isn't available, however for
users who choose not to use GDM or logind, repeating the warning on
each login is more annoying than helpful.
Instead, limit the warning to the first login on which the screen lock
became unavailable. That way the notification will still serve the
intended purpose of informing the user, but without being perceived
as nagging.
https://gitlab.gnome.org/GNOME/gnome-shell/issues/2432
---
js/ui/main.js | 36 +++++++++++++++++++++++++++++++-----
1 file changed, 31 insertions(+), 5 deletions(-)
diff --git a/js/ui/main.js b/js/ui/main.js
index 1203b3c39..a3fad158c 100644
--- a/js/ui/main.js
+++ b/js/ui/main.js
@@ -81,6 +81,9 @@ let _a11ySettings = null;
let _themeResource = null;
let _oskResource = null;
+Gio._promisify(Gio._LocalFilePrototype, 'delete_async', 'delete_finish');
+Gio._promisify(Gio._LocalFilePrototype, 'touch_async', 'touch_finish');
+
function _sessionUpdated() {
if (sessionMode.isPrimary)
_loadDefaultStylesheet();
@@ -242,11 +245,8 @@ function _initializeUI() {
}
if (sessionMode.currentMode !== 'gdm' &&
- sessionMode.currentMode !== 'initial-setup' &&
- screenShield === null) {
- notify(_('Screen Lock disabled'),
- _('Screen Locking requires the GNOME display manager.'));
- }
+ sessionMode.currentMode !== 'initial-setup')
+ _handleLockScreenWarning();
let perfModuleName = GLib.getenv("SHELL_PERF_MODULE");
if (perfModuleName) {
@@ -257,6 +257,32 @@ function _initializeUI() {
});
}
+async function _handleLockScreenWarning() {
+ const path = '%s/lock-warning-shown'.format(global.userdatadir);
+ const file = Gio.File.new_for_path(path);
+
+ const hasLockScreen = screenShield !== null;
+ if (hasLockScreen) {
+ try {
+ await file.delete_async(0, null);
+ } catch (e) {
+ if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+ logError(e);
+ }
+ } else {
+ try {
+ if (!await file.touch_async())
+ return;
+ } catch (e) {
+ logError(e);
+ }
+
+ notify(
+ _('Screen Lock disabled'),
+ _('Screen Locking requires the GNOME display manager.'));
+ }
+}
+
function _getStylesheet(name) {
let stylesheet;
--
2.31.1
From c3f34e786826d0ed1af4150190159fed50d9fb87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Florian=20M=C3=BCllner?= <fmuellner@gnome.org>
Date: Thu, 22 Oct 2020 20:11:14 +0200
Subject: [PATCH 4/4] messageTray: Default to generic policy
How and if notifications are shown is controlled by NotificationPolicy
objects. But ever since 098bd45, only notification daemon sources or
notifications associated with an app are hooked up to GSettings.
The hardcoded default policy for built-in notifications (including
those provided by extensions) arguably made sense back then, but
now that the main setting has been rebranded as "Do Not Disturb"
and is exposed prominently in the calendar drop-down, following
GSettings is a better default.
https://gitlab.gnome.org/GNOME/gnome-shell/-/issues/3291
Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1511>
---
js/ui/messageTray.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js
index 8f8130451..f6bdae8e4 100644
--- a/js/ui/messageTray.js
+++ b/js/ui/messageTray.js
@@ -731,7 +731,7 @@ var Source = class Source {
}
_createPolicy() {
- return new NotificationPolicy();
+ return new NotificationGenericPolicy();
}
get narrowestPrivacyScope() {
--
2.31.1

View File

@ -1,6 +1,6 @@
Name: gnome-shell
Version: 3.32.2
Release: 30%{?dist}
Release: 40%{?dist}
Summary: Window management and application launching for GNOME
Group: User Interface/Desktops
@ -26,6 +26,14 @@ Patch18: 0001-gdm-add-AuthList-control.patch
Patch19: 0002-gdmUtil-enable-support-for-GDM-s-ChoiceList-PAM-exte.patch
Patch20: wake-up-on-deactivate.patch
Patch21: caps-lock-warning.patch
Patch22: gdm-networking.patch
Patch23: 0001-shellEntry-Disconnect-handler-on-destroy.patch
Patch24: fix-login-lock-screen.patch
Patch25: 0001-shellEntry-Determine-if-password-entry-from-content-.patch
Patch26: 0002-shellEntry-Give-password-menu-item-text-when-it-s-cr.patch
Patch27: 0003-shellEntry-Handle-password-item-from-dedication-func.patch
Patch28: 0004-shellEntry-Support-lockdown-of-Show-Text-menu-in-pas.patch
Patch29: 0005-shellEntry-Only-mask-text-in-password-entries.patch
# Misc.
Patch30: 0001-shellDBus-Add-a-DBus-method-to-load-a-single-extensi.patch
@ -51,11 +59,13 @@ Patch49: 0001-Do-not-change-Wacom-LEDs-through-g-s-d.patch
Patch50: 0001-st-texture-cache-Cancel-pending-requests-on-icon-the.patch
Patch51: introspect-backports.patch
Patch52: 0001-popupMenu-Handle-keypress-if-numlock-is-enabled.patch
Patch53: 0001-theme-Update-window-preview-style.patch
Patch54: warn-less.patch
# Backport JS invalid access warnings (#1651894, #1663171, #1642482, #1637622)
Patch54: fix-invalid-access-warnings.patch
Patch55: more-spurious-allocation-warnings.patch
Patch56: fix-some-js-warnings.patch
Patch55: fix-invalid-access-warnings.patch
Patch56: more-spurious-allocation-warnings.patch
Patch57: fix-some-js-warnings.patch
# Backport performance fixes under load (#1820760)
Patch60: 0001-environment-reduce-calls-to-g_time_zone_new_local.patch
@ -78,6 +88,12 @@ Patch10002: 0002-background-rebuild-background-not-just-animation-on-.patch
Patch10003: 0003-st-texture-cache-purge-on-resume.patch
Patch10004: 0004-background-refresh-background-on-gl-video-memory-pur.patch
# Allow login screen extensions (#1651378)
Patch20001: 0001-extensionSystem-Handle-added-or-removed-sessionMode-.patch
Patch20002: 0002-extensionSystem-Get-rid-of-_enabled-boolean-optimiza.patch
Patch20003: 0003-extensionSystem-Allow-extensions-to-run-on-the-login.patch
Patch20004: 0004-sessionMode-Allow-extensions-at-the-login-and-unlock.patch
%define libcroco_version 0.6.8
%define eds_version 3.17.2
%define gnome_desktop_version 3.7.90
@ -85,9 +101,9 @@ Patch10004: 0004-background-refresh-background-on-gl-video-memory-pur.patch
%define gobject_introspection_version 1.49.1
%define gjs_version 1.54.0
%define gtk3_version 3.15.0
%define mutter_version 3.32
%define mutter_version 3.32.2-57
%define polkit_version 0.100
%define gsettings_desktop_schemas_version 3.32.0-3
%define gsettings_desktop_schemas_version 3.32.0-6
%define ibus_version 1.5.2
%define gnome_bluetooth_version 1:3.9.0
%define gstreamer_version 1.4.5
@ -176,6 +192,8 @@ Requires: bolt%{?_isa}
# Needed for launching flatpak apps etc
Requires: xdg-desktop-portal-gtk
Provides: PolicyKit-authentication-agent = %{version}-%{release}
%description
GNOME Shell provides core user interface functions for the GNOME 3 desktop,
like switching to windows and launching applications. GNOME Shell takes
@ -253,9 +271,54 @@ desktop-file-validate %{buildroot}%{_datadir}/applications/evolution-calendar.de
%{_mandir}/man1/%{name}.1.gz
%changelog
* Mon Feb 22 2021 Carlos Garnacho <cgarnach@redhat.com> - 3.32.2-30
* Tue Aug 31 2021 Ray Strode <rstrode@redhat.com> - 3.32.2-40
- Add bugs introduced in backport for #1651378
Related: #1999758
- Tidy up patch list a bit
* Wed Aug 25 2021 Ray Strode <rstrode@redhat.com> - 3.32.2-39
- Allow extensions on the login screen
Related: #1651378
* Thu Jul 29 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-38
- Only mask text in password entries
Resolves: #1987233
* Wed Jul 28 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-37
- Only warn once when not running under GDM
Resolves: #1980661
* Tue Jul 20 2021 Ray Strode <rstrode@redhat.com> - 3.32.2-36
- Add ability to lock down password showing
Resolves: #1770302
- Add requires on newer mutter version
Related: #1937866
* Tue Jul 13 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-35
- Improve style of window preview close buttons
Resolves: #1981420
* Mon Jul 12 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-34
- Add PolicyKit-authentication-agent virtual provides
Resolves: #1978287
* Mon Jun 14 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-33
- Fix warnings on unlock
Resolves: #1971534
- Fix gdm lock screen
Resolves: #1971507
* Thu Jun 10 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-32
- Fix network secret requests on login screen
Related: #1935261
* Wed Jun 09 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-31
- Backport of touch mode
Resolves: #1833787
Resolves: #1937866
* Tue Jun 08 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-30
- Do not disable network actions on login screen
Resolves: #1935261
* Mon Feb 01 2021 Florian Müllner <fmuellner@redhat.com> - 3.32.2-29
- Refuse to override system extensions