diff --git a/0001-Support-for-web-login-and-unified-auth-mechanism.patch b/0001-Support-for-web-login-and-unified-auth-mechanism.patch index 24f1bb4..06de8b9 100644 --- a/0001-Support-for-web-login-and-unified-auth-mechanism.patch +++ b/0001-Support-for-web-login-and-unified-auth-mechanism.patch @@ -1,4 +1,4 @@ -From 898c0e7eda41c0e3f7e53ec0d27bbb3fbee8e2dd Mon Sep 17 00:00:00 2001 +From e2dd023ba86cd60da2482ff603c9fc2f255d4c95 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 2 Oct 2025 10:59:57 +0200 Subject: [PATCH 01/72] style: Add common login dialog button styles to avoid @@ -85,7 +85,7 @@ index b661e93c8..6cca1e28e 100644 2.55.0 -From 622a9064b28f6f3b078c7871ff136a4ab18b6458 Mon Sep 17 00:00:00 2001 +From 0b2bbfa722ca1ccddf97fa0464ee3bf16bfa0243 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 16:37:08 +0100 Subject: [PATCH 02/72] unlockDialog: Vertically center dialog using fixed @@ -164,7 +164,7 @@ index 63ba591ee..a014095bb 100644 2.55.0 -From 0e0c00dd905cf06bf8d90568d02dadf7ff8970be Mon Sep 17 00:00:00 2001 +From 650c4f52cbb1f55ac96c55f131f7172615a0a7dd Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 16:38:04 +0100 Subject: [PATCH 03/72] unlockDialog: Fix username reuse on reset @@ -195,7 +195,7 @@ index a014095bb..420dae4c6 100644 2.55.0 -From 9053be8857ddb04ff70f6f65e73bcd57791f75f1 Mon Sep 17 00:00:00 2001 +From d41d517a601756d8f2b3f886beaea17ae112af38 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 16:38:54 +0100 Subject: [PATCH 04/72] unlockDialog: Wait for authPrompt destruction before @@ -228,7 +228,7 @@ index 420dae4c6..7a02f68ee 100644 2.55.0 -From 465e76688dd01cdb5f2bae01fc3ee01dda6fcefd Mon Sep 17 00:00:00 2001 +From 7ce5fb94b4e9580e6944c0f03c18dcf8e260f5da Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 5 Feb 2026 18:55:38 +0100 Subject: [PATCH 05/72] authPrompt: Use destructured object for @@ -245,7 +245,7 @@ Part-of: 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index b1e8202bd..2adfd1921 100644 +index 3b4a2f798..526dcdbaa 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -287,7 +287,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -275,7 +275,7 @@ index b1e8202bd..2adfd1921 100644 this.emit('prompted'); } -@@ -415,7 +415,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -419,7 +419,7 @@ export const AuthPrompt = GObject.registerClass({ this.clear(); } @@ -284,7 +284,7 @@ index b1e8202bd..2adfd1921 100644 this.setActorInDefaultButtonWell(null); if (!canRetry) -@@ -536,12 +536,12 @@ export const AuthPrompt = GObject.registerClass({ +@@ -540,12 +540,12 @@ export const AuthPrompt = GObject.registerClass({ opacity: 0, visible: true, }); @@ -299,8 +299,8 @@ index b1e8202bd..2adfd1921 100644 }); } -@@ -605,7 +605,7 @@ export const AuthPrompt = GObject.registerClass({ - } +@@ -611,7 +611,7 @@ export const AuthPrompt = GObject.registerClass({ + wiggle(this._message, wiggleParameters); } - updateSensitivity(sensitive) { @@ -308,7 +308,7 @@ index b1e8202bd..2adfd1921 100644 let authWidget; if (this._authList.visible) -@@ -635,7 +635,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -641,7 +641,7 @@ export const AuthPrompt = GObject.registerClass({ this.setUser(null); @@ -317,7 +317,7 @@ index b1e8202bd..2adfd1921 100644 this._entry.set_text(''); } -@@ -728,7 +728,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -734,7 +734,7 @@ export const AuthPrompt = GObject.registerClass({ hold: null, }); @@ -367,7 +367,7 @@ index 7a02f68ee..85e469fb8 100644 2.55.0 -From a703c5d6561bb96b9dbb17c257e6ff4f2ca462bc Mon Sep 17 00:00:00 2001 +From 1eb143ebb879ce44ba8488573366d6633f52320a Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 16:47:22 +0100 Subject: [PATCH 06/72] authPrompt: Use array-based widget lookup in @@ -382,10 +382,10 @@ Part-of: 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 2adfd1921..ab61e14f9 100644 +index 526dcdbaa..7967b60a8 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -606,12 +606,9 @@ export const AuthPrompt = GObject.registerClass({ +@@ -612,12 +612,9 @@ export const AuthPrompt = GObject.registerClass({ } updateSensitivity({sensitive}) { @@ -405,7 +405,7 @@ index 2adfd1921..ab61e14f9 100644 2.55.0 -From ccb5270afbae6869c4c90b7eeefb411b63542c05 Mon Sep 17 00:00:00 2001 +From a2ee935e74e0b98d726fb39506fa45896f011eb3 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 10 Mar 2026 17:10:58 +0100 Subject: [PATCH 07/72] authPrompt: Generalize _fadeInChoiceList to accept any @@ -423,10 +423,10 @@ Part-of: 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index ab61e14f9..7033e05f0 100644 +index 7967b60a8..f00f5844b 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -531,17 +531,18 @@ export const AuthPrompt = GObject.registerClass({ +@@ -535,17 +535,18 @@ export const AuthPrompt = GObject.registerClass({ this._entry.grab_key_focus(); } @@ -451,7 +451,7 @@ index ab61e14f9..7033e05f0 100644 }); } -@@ -556,7 +557,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -560,7 +561,8 @@ export const AuthPrompt = GObject.registerClass({ this._entry.hide(); if (this._message.text === '') this._message.hide(); @@ -465,7 +465,7 @@ index ab61e14f9..7033e05f0 100644 2.55.0 -From 502d46f69121ad2b5a4e2680b9e336a07127ba4d Mon Sep 17 00:00:00 2001 +From 6e9c414d417f719fa9cc625a4d6764a895360444 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Fri, 9 Feb 2024 09:02:25 -0500 Subject: [PATCH 08/72] authPrompt: Fade out input buttons/entry after @@ -483,7 +483,7 @@ Part-of: 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 7033e05f0..6e8666fe7 100644 +index f00f5844b..6dc8e2ebc 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -51,6 +51,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -494,7 +494,7 @@ index 7033e05f0..6e8666fe7 100644 }, }, class AuthPrompt extends St.BoxLayout { _init(gdmClient, mode) { -@@ -428,8 +429,15 @@ export const AuthPrompt = GObject.registerClass({ +@@ -432,8 +433,15 @@ export const AuthPrompt = GObject.registerClass({ _onVerificationComplete() { this.setActorInDefaultButtonWell(null); this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED; @@ -512,7 +512,7 @@ index 7033e05f0..6e8666fe7 100644 } _onReset() { -@@ -516,6 +524,9 @@ export const AuthPrompt = GObject.registerClass({ +@@ -520,6 +528,9 @@ export const AuthPrompt = GObject.registerClass({ this.stopSpinning(); this._authList.clear(); this._authList.hide(); @@ -554,7 +554,7 @@ index 9f76464ad..7992cadb4 100644 2.55.0 -From 2e9f927a1971704f433f661bf7f51e90865ebb62 Mon Sep 17 00:00:00 2001 +From 21755147844867edfa97c9a9fb945a9913aa2e62 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 21 Jan 2026 14:23:34 +0100 Subject: [PATCH 09/72] authPrompt: Don't reset preemptiveAnswer when @@ -572,10 +572,10 @@ Part-of: 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 6e8666fe7..81863f78e 100644 +index 6dc8e2ebc..309fb8981 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -679,7 +679,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -685,7 +685,8 @@ export const AuthPrompt = GObject.registerClass({ this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.cancelButton.reactive = this._hasCancelButton; this.cancelButton.can_focus = this._hasCancelButton; @@ -589,7 +589,7 @@ index 6e8666fe7..81863f78e 100644 2.55.0 -From bc17c345307308f5fdc7b86df98db3dbbb778d88 Mon Sep 17 00:00:00 2001 +From f3484a67fa4beb3291e3b5e9229554b5f112eaca Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:05:32 +0100 Subject: [PATCH 10/72] style: Increase hint-text left margin @@ -618,7 +618,7 @@ index 41e10f766..5a45e86d6 100644 2.55.0 -From a7a989b82b4fede27cf05cb89dc83dfe19820dab Mon Sep 17 00:00:00 2001 +From 6530992b790dd18b6e8d44cbed6a0c6d70125d54 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 16 Feb 2026 16:05:17 +0100 Subject: [PATCH 11/72] authPrompt: Use connectObject for userVerifier signals @@ -633,7 +633,7 @@ Part-of: 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 81863f78e..9fcf48590 100644 +index 309fb8981..2e247d913 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -80,14 +80,16 @@ export const AuthPrompt = GObject.registerClass({ @@ -692,13 +692,13 @@ index 81863f78e..9fcf48590 100644 this.reset(); } -- _onShowMessage(_userVerifier, serviceName, message, type, showMessageResolver) { -+ _onShowMessage(serviceName, message, type, showMessageResolver) { - this.setMessage(message, type); - this.emit('prompted'); +- _onShowMessage(_userVerifier, serviceName, message, type) { ++ _onShowMessage(serviceName, message, type) { + let wiggleParameters = {duration: 0}; -@@ -408,7 +410,7 @@ export const AuthPrompt = GObject.registerClass({ - showMessageResolver?.(wigglePromise); + if (type === GdmUtil.MessageType.ERROR && +@@ -412,7 +414,7 @@ export const AuthPrompt = GObject.registerClass({ + this.emit('prompted'); } - _onVerificationFailed(userVerifier, serviceName, canRetry) { @@ -710,7 +710,7 @@ index 81863f78e..9fcf48590 100644 2.55.0 -From 1d6ee728c8972d771b8daa834687053c66a62ccc Mon Sep 17 00:00:00 2001 +From 9ff8d9da8f10d003ffa53a2cbf23d20483f696b1 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:09:44 +0100 Subject: [PATCH 12/72] authPrompt: Group animation constants together @@ -724,7 +724,7 @@ Part-of: 1 file changed, 1 deletion(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 9fcf48590..4bd0c8f6d 100644 +index 2e247d913..edd30e3fa 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -18,7 +18,6 @@ import {wiggle} from '../misc/animationUtils.js'; @@ -739,7 +739,7 @@ index 9fcf48590..4bd0c8f6d 100644 2.55.0 -From 453008139ebe53795a33f3a6d2dde54a7e8aed45 Mon Sep 17 00:00:00 2001 +From 5113cca1b7092f56ab98d810725a8b833c308f4f Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:20:34 +0100 Subject: [PATCH 13/72] authPrompt: Update entry layout based on mockups @@ -824,7 +824,7 @@ index 46805ebca..3695014f8 100644 .conflicting-session-dialog-content { diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 4bd0c8f6d..23d3fce72 100644 +index edd30e3fa..ec4a63a0e 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -199,10 +199,20 @@ export const AuthPrompt = GObject.registerClass({ @@ -910,7 +910,7 @@ index 4bd0c8f6d..23d3fce72 100644 this._entry = newEntry; this._inactiveEntry = inactiveEntry; -@@ -418,17 +449,17 @@ export const AuthPrompt = GObject.registerClass({ +@@ -422,17 +453,17 @@ export const AuthPrompt = GObject.registerClass({ } this.updateSensitivity({sensitive: canRetry}); @@ -931,7 +931,7 @@ index 4bd0c8f6d..23d3fce72 100644 this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED; this._mainBox.reactive = false; -@@ -539,7 +570,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -543,7 +574,8 @@ export const AuthPrompt = GObject.registerClass({ this._entry.hint_text = question; this._authList.hide(); @@ -941,7 +941,7 @@ index 4bd0c8f6d..23d3fce72 100644 this._entry.grab_key_focus(); } -@@ -566,7 +598,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -570,7 +602,7 @@ export const AuthPrompt = GObject.registerClass({ this._authList.addItem(key, text); } @@ -950,7 +950,7 @@ index 4bd0c8f6d..23d3fce72 100644 if (this._message.text === '') this._message.hide(); this._fadeInElement(this._authList); -@@ -624,8 +656,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -630,8 +662,8 @@ export const AuthPrompt = GObject.registerClass({ this._authList, ].find(widget => widget.visible) ?? this._entry; @@ -961,7 +961,7 @@ index 4bd0c8f6d..23d3fce72 100644 authWidget.reactive = sensitive; -@@ -640,7 +672,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -646,7 +678,7 @@ export const AuthPrompt = GObject.registerClass({ } vfunc_hide() { @@ -974,7 +974,7 @@ index 4bd0c8f6d..23d3fce72 100644 2.55.0 -From 406d4e52d3fc51ec16957dd137ebfc5b944ac812 Mon Sep 17 00:00:00 2001 +From 644167912b2de5e54643159ca4d9c13d94a274ca Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:41:48 +0100 Subject: [PATCH 14/72] authPrompt: Fade in _entryArea instead of abruptly @@ -994,7 +994,7 @@ Part-of: 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 23d3fce72..cf1046f94 100644 +index ec4a63a0e..e8825246d 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -383,7 +383,6 @@ export const AuthPrompt = GObject.registerClass({ @@ -1005,7 +1005,7 @@ index 23d3fce72..cf1046f94 100644 this.emit('prompted'); } -@@ -443,10 +442,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -447,10 +446,8 @@ export const AuthPrompt = GObject.registerClass({ _onVerificationFailed(serviceName, canRetry) { const wasQueryingService = this._queryingService === serviceName; @@ -1017,7 +1017,7 @@ index 23d3fce72..cf1046f94 100644 this.updateSensitivity({sensitive: canRetry}); this.setActorInDefaultButtonWell(this._nextButton); -@@ -551,6 +548,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -555,6 +552,7 @@ export const AuthPrompt = GObject.registerClass({ } clear() { @@ -1025,7 +1025,7 @@ index 23d3fce72..cf1046f94 100644 this._entry.text = ''; this._inactiveEntry.text = ''; this.stopSpinning(); -@@ -571,8 +569,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -575,8 +573,8 @@ export const AuthPrompt = GObject.registerClass({ this._authList.hide(); @@ -1052,7 +1052,7 @@ index 7992cadb4..13605b7a4 100644 2.55.0 -From 8d41aea60d8a313037d856364e40839621965f81 Mon Sep 17 00:00:00 2001 +From 25ae256231f865c53b370f53cc53fb21bebaade4 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:36:08 +0100 Subject: [PATCH 15/72] authPrompt: Show entry area when displaying message @@ -1067,13 +1067,14 @@ Part-of: 1 file changed, 10 insertions(+) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index cf1046f94..6ede6be7c 100644 +index e8825246d..b4b1b4524 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -429,6 +429,16 @@ export const AuthPrompt = GObject.registerClass({ - this.setMessage(message, type); - this.emit('prompted'); +@@ -441,6 +441,16 @@ export const AuthPrompt = GObject.registerClass({ + this.setMessage(message, type, wiggleParameters); + this.emit('prompted'); ++ + // If we're showing a message and no auth widget is currently visible, + // show the entry area to allow getting a preemptive answer + if (message && @@ -1083,15 +1084,14 @@ index cf1046f94..6ede6be7c 100644 + this._fadeInElement(this._entryArea); + this.updateSensitivity({sensitive: true}); + } -+ - const shouldWiggle = type === GdmUtil.MessageType.ERROR && - this._userVerifier.serviceIsFingerprint(serviceName); + } + _onVerificationFailed(serviceName, canRetry) { -- 2.55.0 -From a9755e89022db4cb4be4f325b8c37b1ad43197fb Mon Sep 17 00:00:00 2001 +From f591e498218a34424147491fcf5f03ec534c3aa6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 19 May 2026 10:21:50 +0200 Subject: [PATCH 16/72] authPrompt: Add loading signal @@ -1108,7 +1108,7 @@ Part-of: 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 6ede6be7c..e27c1c329 100644 +index b4b1b4524..6ba29d1f4 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -51,6 +51,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -1119,7 +1119,7 @@ index 6ede6be7c..e27c1c329 100644 }, }, class AuthPrompt extends St.BoxLayout { _init(gdmClient, mode) { -@@ -456,7 +457,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -460,7 +461,7 @@ export const AuthPrompt = GObject.registerClass({ this._queryingService = null; this.updateSensitivity({sensitive: canRetry}); @@ -1128,7 +1128,7 @@ index 6ede6be7c..e27c1c329 100644 if (!canRetry) this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED; -@@ -466,7 +467,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -470,7 +471,7 @@ export const AuthPrompt = GObject.registerClass({ } _onVerificationComplete() { @@ -1137,7 +1137,7 @@ index 6ede6be7c..e27c1c329 100644 this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED; this._mainBox.reactive = false; -@@ -549,12 +550,14 @@ export const AuthPrompt = GObject.registerClass({ +@@ -553,12 +554,14 @@ export const AuthPrompt = GObject.registerClass({ this._defaultButtonWellActor = actor; } @@ -1156,7 +1156,7 @@ index 6ede6be7c..e27c1c329 100644 } clear() { -@@ -680,7 +683,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -686,7 +689,7 @@ export const AuthPrompt = GObject.registerClass({ } vfunc_hide() { @@ -1169,7 +1169,7 @@ index 6ede6be7c..e27c1c329 100644 2.55.0 -From 7b06c441ad7dcd0195657ce2a18f844337d6ae7b Mon Sep 17 00:00:00 2001 +From 96b6c98978c709613fae0871ef4e1729ac1e9f79 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 19 May 2026 10:24:38 +0200 Subject: [PATCH 17/72] authPrompt: Don't delay spinner @@ -1187,7 +1187,7 @@ Part-of: 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index e27c1c329..45c77df39 100644 +index 6ba29d1f4..881aae715 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -16,7 +16,6 @@ import * as UserWidget from '../ui/userWidget.js'; @@ -1198,7 +1198,7 @@ index e27c1c329..45c77df39 100644 const DEFAULT_BUTTON_WELL_ANIMATION_TIME = 300; const MESSAGE_FADE_OUT_ANIMATION_TIME = 500; -@@ -519,7 +518,6 @@ export const AuthPrompt = GObject.registerClass({ +@@ -523,7 +522,6 @@ export const AuthPrompt = GObject.registerClass({ oldActor.ease({ opacity: 0, duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, @@ -1206,7 +1206,7 @@ index e27c1c329..45c77df39 100644 mode: Clutter.AnimationMode.LINEAR, onComplete: () => { if (wasSpinner) { -@@ -541,7 +539,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -545,7 +543,7 @@ export const AuthPrompt = GObject.registerClass({ actor.ease({ opacity: 255, duration: DEFAULT_BUTTON_WELL_ANIMATION_TIME, @@ -1219,7 +1219,7 @@ index e27c1c329..45c77df39 100644 2.55.0 -From c98ca7986406c6f2afff0842039286ce57173733 Mon Sep 17 00:00:00 2001 +From 7087b1823f601daf13aaf6e06ce36e05465dacaf Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 17:28:54 +0100 Subject: [PATCH 18/72] authPrompt: Simplify some code @@ -1230,7 +1230,7 @@ Part-of: 1 file changed, 40 insertions(+), 54 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 45c77df39..0192db381 100644 +index 881aae715..e3b8df559 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -241,11 +241,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -1268,7 +1268,7 @@ index 45c77df39..0192db381 100644 this._userVerifier.answerQuery(this._queryingService, this._entry.text); } else { this._preemptiveAnswer = this._entry.text; -@@ -485,64 +484,51 @@ export const AuthPrompt = GObject.registerClass({ +@@ -489,64 +488,51 @@ export const AuthPrompt = GObject.registerClass({ } setActorInDefaultButtonWell(actor, animate) { @@ -1369,7 +1369,7 @@ index 45c77df39..0192db381 100644 2.55.0 -From d26fcef697855a6990b93c94832fa465877ed333 Mon Sep 17 00:00:00 2001 +From dfb1247b4779a4cb085cb865ecc2a47a1ae672c0 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 26 May 2026 16:48:43 +0200 Subject: [PATCH 19/72] authPrompt: Ensure this._message is always visible @@ -1384,10 +1384,10 @@ Part-of: 1 file changed, 3 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 0192db381..60a5a4300 100644 +index e3b8df559..5518c9c03 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -594,8 +594,6 @@ export const AuthPrompt = GObject.registerClass({ +@@ -598,8 +598,6 @@ export const AuthPrompt = GObject.registerClass({ } this._entryArea.hide(); @@ -1396,7 +1396,7 @@ index 0192db381..60a5a4300 100644 this._fadeInElement(this._authList); this.updateSensitivity({sensitive: true}); } -@@ -635,7 +633,6 @@ export const AuthPrompt = GObject.registerClass({ +@@ -639,7 +637,6 @@ export const AuthPrompt = GObject.registerClass({ else this._message.remove_style_class_name('login-dialog-message-hint'); @@ -1408,7 +1408,7 @@ index 0192db381..60a5a4300 100644 2.55.0 -From a25f4822dc914adb9aecf0b2d64c2921d040a550 Mon Sep 17 00:00:00 2001 +From c2b84b38e09c0c6a3c795ccd30d2e6159151bfed Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 10 Mar 2026 18:32:48 +0100 Subject: [PATCH 20/72] authPrompt: Skip reset after successful verification @@ -1421,10 +1421,10 @@ Part-of: 1 file changed, 3 insertions(+) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 60a5a4300..0550d2659 100644 +index 5518c9c03..02dd296f1 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -479,6 +479,9 @@ export const AuthPrompt = GObject.registerClass({ +@@ -483,6 +483,9 @@ export const AuthPrompt = GObject.registerClass({ } _onReset() { @@ -1438,7 +1438,7 @@ index 60a5a4300..0550d2659 100644 2.55.0 -From 4ae886f514dafa62f525f4a1f42249059b05a750 Mon Sep 17 00:00:00 2001 +From e0596d49377f639a8868e66fd15961766699f22c Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 13:06:32 -0500 Subject: [PATCH 21/72] authPrompt: Parameterize reset function @@ -1455,7 +1455,7 @@ Part-of: 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 0550d2659..5d58d62af 100644 +index 02dd296f1..911b1f969 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -85,7 +85,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -1467,7 +1467,7 @@ index 0550d2659..5d58d62af 100644 'smartcard-status-changed', () => this._onSmartcardStatusChanged(), 'credential-manager-authenticated', () => this._onCredentialManagerAuthenticated(), this); -@@ -478,12 +478,11 @@ export const AuthPrompt = GObject.registerClass({ +@@ -482,12 +482,11 @@ export const AuthPrompt = GObject.registerClass({ this.emit('verification-complete'); } @@ -1482,7 +1482,7 @@ index 0550d2659..5d58d62af 100644 } setActorInDefaultButtonWell(actor, animate) { -@@ -547,11 +546,18 @@ export const AuthPrompt = GObject.registerClass({ +@@ -551,11 +550,18 @@ export const AuthPrompt = GObject.registerClass({ this.setActorInDefaultButtonWell(this._nextButton, animate); } @@ -1506,7 +1506,7 @@ index 0550d2659..5d58d62af 100644 this._authList.clear(); this._authList.hide(); -@@ -702,8 +708,13 @@ export const AuthPrompt = GObject.registerClass({ +@@ -708,8 +714,13 @@ export const AuthPrompt = GObject.registerClass({ this.updateSensitivity(false); } @@ -1522,7 +1522,7 @@ index 0550d2659..5d58d62af 100644 this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; this.cancelButton.reactive = this._hasCancelButton; this.cancelButton.can_focus = this._hasCancelButton; -@@ -719,7 +730,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -725,7 +736,7 @@ export const AuthPrompt = GObject.registerClass({ this._userVerifier.cancel(); this._queryingService = null; @@ -1531,7 +1531,7 @@ index 0550d2659..5d58d62af 100644 this._message.opacity = 0; this.setUser(null); this._updateEntry(true); -@@ -742,7 +753,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -748,7 +759,8 @@ export const AuthPrompt = GObject.registerClass({ // We don't need to know the username if the user preempted the login screen // with a smartcard or with preauthenticated oVirt credentials beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME; @@ -1545,7 +1545,7 @@ index 0550d2659..5d58d62af 100644 2.55.0 -From b5375704f551681027a73dd53d43ca10e6954c34 Mon Sep 17 00:00:00 2001 +From 6fe14f86ec91dd28ba4b0a73704b043ea36ee60f Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 19 May 2026 15:18:23 +0200 Subject: [PATCH 22/72] authPrompt: Remove this.stopSpinnning() in reset @@ -1558,10 +1558,10 @@ Part-of: 1 file changed, 1 deletion(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 5d58d62af..4b92fd453 100644 +index 911b1f969..6e1c20f3b 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -734,7 +734,6 @@ export const AuthPrompt = GObject.registerClass({ +@@ -740,7 +740,6 @@ export const AuthPrompt = GObject.registerClass({ this._message.opacity = 0; this.setUser(null); this._updateEntry(true); @@ -1573,7 +1573,7 @@ index 5d58d62af..4b92fd453 100644 2.55.0 -From 6769207733854f56fccf236a6309de25ee5924ae Mon Sep 17 00:00:00 2001 +From 12aa1f7cccb8934e011b6e2fec6605ee285bd0ca Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 21 Apr 2026 13:06:57 +0200 Subject: [PATCH 23/72] authPrompt: Ensure hint_text in entries is cleared @@ -1589,10 +1589,10 @@ Part-of: 1 file changed, 2 insertions(+) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 4b92fd453..1f8f555b0 100644 +index 6e1c20f3b..e8c02f475 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -552,6 +552,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -556,6 +556,8 @@ export const AuthPrompt = GObject.registerClass({ }); if (!reuseEntryText) { @@ -1605,7 +1605,7 @@ index 4b92fd453..1f8f555b0 100644 2.55.0 -From 3652a7defc841415f77c05362c27837f6d34631d Mon Sep 17 00:00:00 2001 +From 3997c46217b221662c7b7bc85cbaf3196f7406d3 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 3 Jul 2026 13:06:26 +0200 Subject: [PATCH 24/72] authPrompt: Separate user and entry updates @@ -1627,7 +1627,7 @@ Part-of: 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 1f8f555b0..996b3710a 100644 +index e8c02f475..86ab75c98 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -338,7 +338,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -1648,7 +1648,7 @@ index 1f8f555b0..996b3710a 100644 // Hack: The question string comes directly from PAM, if it's "Password:" // we replace it with our own to allow localization, if it's something -@@ -692,9 +692,6 @@ export const AuthPrompt = GObject.registerClass({ +@@ -698,9 +698,6 @@ export const AuthPrompt = GObject.registerClass({ let userWidget = new UserWidget.UserWidget(user, Clutter.Orientation.VERTICAL); this._userWell.set_child(userWidget); @@ -1658,7 +1658,7 @@ index 1f8f555b0..996b3710a 100644 } _onUserStoppedTypePreemptiveAnswer() { -@@ -735,7 +732,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -741,7 +738,7 @@ export const AuthPrompt = GObject.registerClass({ this.clear({reuseEntryText}); this._message.opacity = 0; this.setUser(null); @@ -1683,7 +1683,7 @@ index 13605b7a4..2bfaf25f8 100644 2.55.0 -From 1989361b8a715346124e53489a1362ee069bc8a8 Mon Sep 17 00:00:00 2001 +From 3c5a63ef9f3bf14f992ee399b01bac2d9738f3aa Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 12 Feb 2026 16:56:48 +0100 Subject: [PATCH 25/72] authPrompt: Rename BeginRequestType to ResetType @@ -1699,7 +1699,7 @@ Part-of: 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 996b3710a..e16d3f291 100644 +index 86ab75c98..7bca8a1a9 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -36,7 +36,7 @@ export const AuthPromptStatus = { @@ -1711,7 +1711,7 @@ index 996b3710a..e16d3f291 100644 PROVIDE_USERNAME: 0, DONT_PROVIDE_USERNAME: 1, REUSE_USERNAME: 2, -@@ -739,28 +739,28 @@ export const AuthPrompt = GObject.registerClass({ +@@ -745,28 +745,28 @@ export const AuthPrompt = GObject.registerClass({ else if (oldStatus === AuthPromptStatus.VERIFICATION_CANCELLED) this.emit('cancelled'); @@ -1793,7 +1793,7 @@ index 85e469fb8..980353fe1 100644 2.55.0 -From be42e046e2170919cfff0e9bc9cfde933c2f47d8 Mon Sep 17 00:00:00 2001 +From 758ba0bd1e39d1a907d7c5f2af5d48134233a450 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 11 Feb 2026 16:11:59 +0100 Subject: [PATCH 26/72] unlockDialog: Use isprint() instead of isgraph() for @@ -1825,7 +1825,7 @@ index 980353fe1..b0f51e533 100644 2.55.0 -From ceb6e2b0e1e2c6a2715f3c116abbbd621d38097d Mon Sep 17 00:00:00 2001 +From 4eba654ea5b6509107479b247de429e9fd2e37ce Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 21 Jan 2026 14:34:11 +0100 Subject: [PATCH 27/72] authPrompt: Capture preemptive input before entry is @@ -1853,7 +1853,7 @@ Part-of: 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index e16d3f291..6fa69293a 100644 +index 7bca8a1a9..4b9d3961e 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -335,6 +335,8 @@ export const AuthPrompt = GObject.registerClass({ @@ -1890,7 +1890,7 @@ index e16d3f291..6fa69293a 100644 this.setChoiceList(promptMessage, choiceList); this.updateSensitivity({sensitive: true}); -@@ -655,6 +658,9 @@ export const AuthPrompt = GObject.registerClass({ +@@ -661,6 +664,9 @@ export const AuthPrompt = GObject.registerClass({ } updateSensitivity({sensitive}) { @@ -1900,7 +1900,7 @@ index e16d3f291..6fa69293a 100644 const authWidget = [ this._authList, ].find(widget => widget.visible) ?? this._entry; -@@ -708,7 +714,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -714,7 +720,7 @@ export const AuthPrompt = GObject.registerClass({ } reset(params) { @@ -1909,7 +1909,7 @@ index e16d3f291..6fa69293a 100644 reuseEntryText: false, softReset: false, }); -@@ -728,6 +734,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -734,6 +740,8 @@ export const AuthPrompt = GObject.registerClass({ if (this._userVerifier) this._userVerifier.cancel(); @@ -1918,7 +1918,7 @@ index e16d3f291..6fa69293a 100644 this._queryingService = null; this.clear({reuseEntryText}); this._message.opacity = 0; -@@ -763,12 +771,16 @@ export const AuthPrompt = GObject.registerClass({ +@@ -769,12 +777,16 @@ export const AuthPrompt = GObject.registerClass({ this.emit('reset', resetType); } @@ -1940,7 +1940,7 @@ index e16d3f291..6fa69293a 100644 } begin(params) { -@@ -777,7 +789,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -783,7 +795,8 @@ export const AuthPrompt = GObject.registerClass({ hold: null, }); @@ -1982,7 +1982,7 @@ index b0f51e533..100990acc 100644 2.55.0 -From ae380541ccdf30d525235c4d4f74e3c1b2311826 Mon Sep 17 00:00:00 2001 +From f366644aef20288e5adee6524a0e1f255556dfd7 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 10 Feb 2026 18:51:41 +0100 Subject: [PATCH 28/72] authPrompt: On verificationFailed allow a @@ -2000,10 +2000,10 @@ Part-of: 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 6fa69293a..9d2c2d0b4 100644 +index 4b9d3961e..7dc432ba0 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -457,7 +457,11 @@ export const AuthPrompt = GObject.registerClass({ +@@ -461,7 +461,11 @@ export const AuthPrompt = GObject.registerClass({ if (wasQueryingService) this._queryingService = null; @@ -2016,7 +2016,7 @@ index 6fa69293a..9d2c2d0b4 100644 this.stopSpinning(); if (!canRetry) -@@ -734,7 +738,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -740,7 +744,7 @@ export const AuthPrompt = GObject.registerClass({ if (this._userVerifier) this._userVerifier.cancel(); @@ -2029,7 +2029,7 @@ index 6fa69293a..9d2c2d0b4 100644 2.55.0 -From caa66bae4e0356d444a109f045f989c1e0330bfd Mon Sep 17 00:00:00 2001 +From 145ad91b2a1c33a5830fe378df2cc861ff91e2e6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 30 Sep 2025 17:43:22 +0200 Subject: [PATCH 29/72] authPrompt: Update authList style @@ -2429,7 +2429,7 @@ index 4873a05c5..81c204e7f 100644 -}); +} diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 9d2c2d0b4..56dfef305 100644 +index 7dc432ba0..24ac39d5e 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -179,25 +179,46 @@ export const AuthPrompt = GObject.registerClass({ @@ -2486,7 +2486,7 @@ index 9d2c2d0b4..56dfef305 100644 this._entryArea = new St.Widget({ style_class: 'login-dialog-prompt-entry-area', -@@ -567,6 +588,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -571,6 +592,7 @@ export const AuthPrompt = GObject.registerClass({ this.stopSpinning(); } @@ -2494,7 +2494,7 @@ index 9d2c2d0b4..56dfef305 100644 this._authList.clear(); this._authList.hide(); -@@ -605,10 +627,10 @@ export const AuthPrompt = GObject.registerClass({ +@@ -609,10 +631,10 @@ export const AuthPrompt = GObject.registerClass({ setChoiceList(promptMessage, choiceList) { this._authList.clear(); @@ -2510,10 +2510,10 @@ index 9d2c2d0b4..56dfef305 100644 this._entryArea.hide(); diff --git a/js/gdm/util.js b/js/gdm/util.js -index e529f84fa..72ee9d29b 100644 +index 4b0f763f0..b71251458 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -730,7 +730,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -723,7 +723,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { if (!this.serviceIsForeground(serviceName)) return; @@ -2530,7 +2530,7 @@ index e529f84fa..72ee9d29b 100644 2.55.0 -From 87c6792190c9cbdd258ba78c262e8d63b7e1d43c Mon Sep 17 00:00:00 2001 +From a3e973b0f8374a8da6dc427f8538335c1877bf99 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 8 Oct 2025 18:48:07 +0200 Subject: [PATCH 30/72] authPrompt: Let back button go back to step 1 instead @@ -2549,7 +2549,7 @@ Part-of: 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 56dfef305..034357d9f 100644 +index 24ac39d5e..80ef3182f 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -68,6 +68,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -2627,7 +2627,7 @@ index 56dfef305..034357d9f 100644 this._clearPreemptiveState(); -@@ -747,10 +757,10 @@ export const AuthPrompt = GObject.registerClass({ +@@ -753,10 +763,10 @@ export const AuthPrompt = GObject.registerClass({ const oldStatus = this.verificationStatus; this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; @@ -2640,7 +2640,7 @@ index 56dfef305..034357d9f 100644 if (this._preemptiveAnswerWatchId) this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); -@@ -844,6 +854,12 @@ export const AuthPrompt = GObject.registerClass({ +@@ -850,6 +860,12 @@ export const AuthPrompt = GObject.registerClass({ if (this.verificationStatus === AuthPromptStatus.VERIFICATION_SUCCEEDED) return; @@ -2657,7 +2657,7 @@ index 56dfef305..034357d9f 100644 2.55.0 -From 778b7929c3ed03f78ea2ec1cea08ad82338d04e4 Mon Sep 17 00:00:00 2001 +From 26864bbe9e89e118f4a403cd31fb4ea6e22bf8d5 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 20 Oct 2025 17:24:40 +0200 Subject: [PATCH 31/72] loginDialog: Vertically center authPrompt using fixed @@ -2726,7 +2726,7 @@ index 9355eef45..b098891c4 100644 2.55.0 -From 728c933fd1bf44beb24075cd6356663baa5baa39 Mon Sep 17 00:00:00 2001 +From 6a76eea20af043c00d0ae766e9f669c6897d654e Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 12 Nov 2024 14:26:30 -0500 Subject: [PATCH 32/72] data: Add fingerprint and vcard icons @@ -2819,7 +2819,7 @@ index 000000000..1694f2364 2.55.0 -From ebb66897244e15aee81d9417bed4df413b0e332d Mon Sep 17 00:00:00 2001 +From 4f5ac0c62d500b7fc3c3d498c958accd2f22f7f8 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 18 Aug 2025 12:30:50 +0200 Subject: [PATCH 33/72] gdm: Extract authentication service and role constants @@ -2841,7 +2841,7 @@ Part-of: create mode 100644 js/gdm/constants.js diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 034357d9f..1f21d5ba8 100644 +index 80ef3182f..34285015a 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -9,6 +9,7 @@ import St from 'gi://St'; @@ -2876,7 +2876,7 @@ index 000000000..2b6061578 +export const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; +export const SWITCHABLE_AUTH_SERVICE_NAME = 'gdm-switchable-auth'; diff --git a/js/gdm/util.js b/js/gdm/util.js -index 72ee9d29b..0d73d4f33 100644 +index b71251458..0c8ce34d3 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -5,6 +5,7 @@ import GLib from 'gi://GLib'; @@ -2897,7 +2897,7 @@ index 72ee9d29b..0d73d4f33 100644 const CLONE_FADE_ANIMATION_TIME = 250; export const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; -@@ -438,7 +436,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -431,7 +429,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._updateDefaultService(); if (this._userVerifier && @@ -2906,7 +2906,7 @@ index 72ee9d29b..0d73d4f33 100644 if (!this._hold?.isAcquired()) this._hold = new Batch.Hold(); await this._maybeStartFingerprintVerification(); -@@ -492,8 +490,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -485,8 +483,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { this.smartcardDetected = smartcardDetected; if (this.smartcardDetected) @@ -2917,7 +2917,7 @@ index 72ee9d29b..0d73d4f33 100644 this._preemptingService = null; this._updateDefaultService(); -@@ -612,7 +610,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -605,7 +603,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { return true; } @@ -2926,7 +2926,7 @@ index 72ee9d29b..0d73d4f33 100644 } serviceIsDefault(serviceName) { -@@ -621,7 +619,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -614,7 +612,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { serviceIsFingerprint(serviceName) { return this._fingerprintReaderType !== FingerprintReaderType.NONE && @@ -2935,7 +2935,7 @@ index 72ee9d29b..0d73d4f33 100644 } _onSettingsChanged() { -@@ -638,7 +636,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -631,7 +629,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._fingerprintManager = null; this._fingerprintReaderType = FingerprintReaderType.NONE; @@ -2944,7 +2944,7 @@ index 72ee9d29b..0d73d4f33 100644 needsReset = true; } -@@ -648,7 +646,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -641,7 +639,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._smartcardManager.disconnectObject(this); this._smartcardManager = null; @@ -2953,7 +2953,7 @@ index 72ee9d29b..0d73d4f33 100644 needsReset = true; } -@@ -658,13 +656,13 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -651,13 +649,13 @@ export class ShellUserVerifier extends Signals.EventEmitter { _getDetectedDefaultService() { if (this._smartcardManager?.loggedInWithToken()) @@ -2971,7 +2971,7 @@ index 72ee9d29b..0d73d4f33 100644 return null; } -@@ -674,7 +672,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -667,7 +665,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { if (!this._defaultService) { log('no authentication service is enabled, using password authentication'); @@ -2980,7 +2980,7 @@ index 72ee9d29b..0d73d4f33 100644 } if (oldDefaultService && -@@ -722,8 +720,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -715,8 +713,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { async _maybeStartFingerprintVerification() { if (this._userName && this._fingerprintReaderType !== FingerprintReaderType.NONE && @@ -2991,7 +2991,7 @@ index 72ee9d29b..0d73d4f33 100644 } _onChoiceListQuery(client, serviceName, promptMessage, list) { -@@ -855,7 +853,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -848,7 +846,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { } async _verificationFailed(serviceName, shouldRetry) { @@ -3016,7 +3016,7 @@ index e5e6167f1..041365e5d 100644 2.55.0 -From b1ba23ecb626825936df0ad06ca358e992acd80b Mon Sep 17 00:00:00 2001 +From 08ce990483708391e0608a2d84621c06b89c414f Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 11 Mar 2026 11:41:40 +0100 Subject: [PATCH 34/72] gdm/util: Add helper functions to get future mechanisms @@ -3034,7 +3034,7 @@ Part-of: 1 file changed, 34 insertions(+) diff --git a/js/gdm/util.js b/js/gdm/util.js -index 0d73d4f33..304459c71 100644 +index 0c8ce34d3..f0b99a0ff 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -99,6 +99,40 @@ export function cloneAndFadeOutActor(actor) { @@ -3082,7 +3082,7 @@ index 0d73d4f33..304459c71 100644 2.55.0 -From 128705e5fbfb2ef76c305f6bf433cd27bd055008 Mon Sep 17 00:00:00 2001 +From c94bdcc0a865dddb40c894df3c7544685eb1a224 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 11:04:20 -0500 Subject: [PATCH 35/72] gdm: Add new AuthMenuButton control @@ -3718,7 +3718,7 @@ index 041365e5d..d8820876a 100644 2.55.0 -From 8d057f6b1556553412e7225402578be8da0f2de1 Mon Sep 17 00:00:00 2001 +From eb4ada47d1754d8d7bbef06d6cbbec9ecb9b5290 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 11:11:32 -0500 Subject: [PATCH 36/72] loginDialog: Port sessions menu over to AuthMenuButton @@ -3747,7 +3747,7 @@ index e9a1e1a62..572ce9f59 100644 @extend .icon-button; @extend %system_button; diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index b098891c4..deb9d9918 100644 +index b098891c4..92c6aeb67 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -27,6 +27,7 @@ import Pango from 'gi://Pango'; @@ -4041,7 +4041,7 @@ index b098891c4..deb9d9918 100644 2.55.0 -From 0a0e3790160f59baf7e93fa46a0fbe04c36ade1d Mon Sep 17 00:00:00 2001 +From 8d5a2dbffebe6438c3972f7b958c280c7aa437d1 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 13:40:26 -0500 Subject: [PATCH 37/72] loginDialog: Add login options menu to AuthMenuButton @@ -4073,7 +4073,7 @@ Part-of: 3 files changed, 66 insertions(+), 2 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 1f21d5ba8..cce46e178 100644 +index 34285015a..68a209586 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -49,6 +49,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -4092,7 +4092,7 @@ index 1f21d5ba8..cce46e178 100644 'verification-failed', (_, ...args) => this._onVerificationFailed(...args), 'verification-complete', () => this._onVerificationComplete(), 'reset', (_, ...args) => this._onReset(...args), -@@ -750,6 +752,24 @@ export const AuthPrompt = GObject.registerClass({ +@@ -756,6 +758,24 @@ export const AuthPrompt = GObject.registerClass({ this.updateSensitivity(false); } @@ -4118,7 +4118,7 @@ index 1f21d5ba8..cce46e178 100644 let {reuseEntryText, softReset} = Params.parse(params, { reuseEntryText: false, diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index deb9d9918..f88310a6b 100644 +index 92c6aeb67..bbbb1f6b7 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -49,6 +49,7 @@ const _SCROLL_ANIMATION_TIME = 500; @@ -4207,7 +4207,7 @@ index deb9d9918..f88310a6b 100644 this._authMenuButton.setActiveItem({ sectionName: _SESSION_TYPE_SECTION_NAME, diff --git a/js/gdm/util.js b/js/gdm/util.js -index 304459c71..ad4236e88 100644 +index f0b99a0ff..8681cfd1d 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -219,6 +219,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { @@ -4226,7 +4226,7 @@ index 304459c71..ad4236e88 100644 2.55.0 -From d1b4d1b0a5a991b16fd6abeecd58a08893b05131 Mon Sep 17 00:00:00 2001 +From ce010332fe9c5c7a2162f3b6fa13cbde1337e915 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 3 Jul 2026 13:54:39 +0200 Subject: [PATCH 38/72] loginDialog: Restore bottom button group on reset @@ -4241,7 +4241,7 @@ Part-of: 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index f88310a6b..cdb64d322 100644 +index bbbb1f6b7..e0cd0555a 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -1056,6 +1056,7 @@ export const LoginDialog = GObject.registerClass({ @@ -4285,7 +4285,7 @@ index f88310a6b..cdb64d322 100644 2.55.0 -From 15fee32aa9b2d3b75822f950d5986a7516808854 Mon Sep 17 00:00:00 2001 +From c59820c4ce37c60d345c2e8ec9d6eb250ae19e55 Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 13:41:39 -0500 Subject: [PATCH 39/72] unlockDialog: Add _authMenuButton and @@ -4586,7 +4586,7 @@ index 100990acc..d54d21093 100644 2.55.0 -From 1a8e582a2728590d1990f39c81529a0261a9a661 Mon Sep 17 00:00:00 2001 +From c7ebc76a0d0992e99a526176f4b811cfba65d8be Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 3 Dec 2024 07:39:32 -0500 Subject: [PATCH 40/72] unlockDialog: Update hint text based on mockup @@ -4643,7 +4643,7 @@ index d54d21093..38d7b97c4 100644 2.55.0 -From 19b219118b53d8a9d28623fecbfe9985cfa9e8a5 Mon Sep 17 00:00:00 2001 +From 3ab9dac3fdf5accfdcf5a032365facb52a5a368d Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 14 Oct 2025 19:19:15 +0200 Subject: [PATCH 41/72] gdm/util: Increase time of messages based on new @@ -4658,7 +4658,7 @@ Part-of: 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/js/gdm/util.js b/js/gdm/util.js -index ad4236e88..a198bcc32 100644 +index 8681cfd1d..28de988f3 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -44,6 +44,10 @@ export const DISABLE_USER_LIST_KEY = 'disable-user-list'; @@ -4686,7 +4686,7 @@ index ad4236e88..a198bcc32 100644 2.55.0 -From 36666e6ce2a3c180413b3ca784fe68f491f37e84 Mon Sep 17 00:00:00 2001 +From b33a170b13fac927de596af74c8c620c11b7b475 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 15 Sep 2025 17:13:17 +0200 Subject: [PATCH 42/72] gdm/util: Allow null _hold and don't recreate dummy @@ -4710,10 +4710,10 @@ Part-of: 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index cce46e178..00d6a6255 100644 +index 68a209586..d29fc5478 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -849,11 +849,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -855,11 +855,7 @@ export const AuthPrompt = GObject.registerClass({ if (!this._preemptiveInput) this.updateSensitivity({sensitive: false}); @@ -4727,10 +4727,10 @@ index cce46e178..00d6a6255 100644 } diff --git a/js/gdm/util.js b/js/gdm/util.js -index a198bcc32..9df2c76d4 100644 +index 28de988f3..53b4094e0 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -480,11 +480,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -473,11 +473,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._updateDefaultService(); if (this._userVerifier && @@ -4743,7 +4743,7 @@ index a198bcc32..9df2c76d4 100644 } _setFingerprintReaderType(fprintDeviceType) { -@@ -546,7 +543,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -539,7 +536,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { _reportInitError(where, error, serviceName) { logError(error, where); @@ -4752,7 +4752,7 @@ index a198bcc32..9df2c76d4 100644 this._queueMessage(serviceName, _('Authentication error'), MessageType.ERROR); this._failCounter++; -@@ -584,7 +581,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -577,7 +574,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this.reauthenticating = true; this._connectSignals(); this._beginVerification(); @@ -4761,7 +4761,7 @@ index a198bcc32..9df2c76d4 100644 } async _getUserVerifier() { -@@ -608,7 +605,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -601,7 +598,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._connectSignals(); this._beginVerification(); @@ -4770,7 +4770,7 @@ index a198bcc32..9df2c76d4 100644 } _connectSignals() { -@@ -726,7 +723,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -719,7 +716,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { } async _startService(serviceName) { @@ -4779,7 +4779,7 @@ index a198bcc32..9df2c76d4 100644 try { this._activeServices.add(serviceName); if (this._userName) { -@@ -743,7 +740,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -736,7 +733,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { if (!this.serviceIsForeground(serviceName)) { logError(e, `Failed to start ${serviceName} for ${this._userName}`); @@ -4788,7 +4788,7 @@ index a198bcc32..9df2c76d4 100644 return; } this._reportInitError( -@@ -753,7 +750,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -746,7 +743,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { e, serviceName); return; } @@ -4797,7 +4797,7 @@ index a198bcc32..9df2c76d4 100644 } _beginVerification() { -@@ -886,7 +883,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -879,7 +876,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { } _retry(serviceName) { @@ -4809,7 +4809,7 @@ index a198bcc32..9df2c76d4 100644 2.55.0 -From 6852a3faf63a79d26555c91f7d8e679a3d2ab171 Mon Sep 17 00:00:00 2001 +From 6b1702852b3982518edec5998d5bb457d956125a Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 20 Aug 2025 10:54:33 +0200 Subject: [PATCH 43/72] gdm: Add FingerprintManager @@ -4975,7 +4975,7 @@ index 000000000..2577facbb + } +} diff --git a/js/gdm/util.js b/js/gdm/util.js -index 9df2c76d4..14d581714 100644 +index 53b4094e0..44795129e 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -6,19 +6,14 @@ import * as Signals from '../misc/signals.js'; @@ -5040,7 +5040,7 @@ index 9df2c76d4..14d581714 100644 this._fingerprintManager = null; for (let service in this._credentialManagers) -@@ -385,111 +375,39 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -378,111 +368,39 @@ export class ShellUserVerifier extends Signals.EventEmitter { } async _initFingerprintManager() { @@ -5175,7 +5175,7 @@ index 9df2c76d4..14d581714 100644 } _onCredentialManagerAuthenticated(credentialManager, _token) { -@@ -659,7 +577,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -652,7 +570,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { } serviceIsFingerprint(serviceName) { @@ -5184,7 +5184,7 @@ index 9df2c76d4..14d581714 100644 serviceName === Constants.FINGERPRINT_SERVICE_NAME; } -@@ -672,10 +590,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -665,10 +583,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { let needsReset = false; if (this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY)) { @@ -5199,7 +5199,7 @@ index 9df2c76d4..14d581714 100644 if (this._activeServices.has(Constants.FINGERPRINT_SERVICE_NAME)) needsReset = true; -@@ -702,7 +622,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -695,7 +615,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { return Constants.PASSWORD_SERVICE_NAME; else if (this._smartcardManager) return Constants.SMARTCARD_SERVICE_NAME; @@ -5208,7 +5208,7 @@ index 9df2c76d4..14d581714 100644 return Constants.FINGERPRINT_SERVICE_NAME; return null; } -@@ -760,7 +680,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -753,7 +673,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { async _maybeStartFingerprintVerification() { if (this._userName && @@ -5217,7 +5217,7 @@ index 9df2c76d4..14d581714 100644 !this.serviceIsForeground(Constants.FINGERPRINT_SERVICE_NAME)) await this._startService(Constants.FINGERPRINT_SERVICE_NAME); } -@@ -783,7 +703,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -776,7 +696,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { // We don't show fingerprint messages directly since it's // not the main auth service. Instead we use the messages // as a cue to display our own message. @@ -5242,7 +5242,7 @@ index d8820876a..50e0b179a 100644 2.55.0 -From e5a352f03c2139e78f48cfbcfa250080632346da Mon Sep 17 00:00:00 2001 +From 920955f9a545cdc8b7e73a96529773ca3a320fa3 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 23 Sep 2025 16:45:59 +0200 Subject: [PATCH 44/72] gdm: Add PasskeyDeviceManager @@ -5364,7 +5364,7 @@ index f8f98d487..c3c51aa2d 100644 2.55.0 -From 6996a2bbd8c5197be87dfe10594a02a61110d788 Mon Sep 17 00:00:00 2001 +From 7552b0a502fd53960abdba0c406fcccf2d92c1b7 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 19 May 2026 20:33:29 +0200 Subject: [PATCH 45/72] gdm: Move smartcardManager.js to gdm @@ -5399,7 +5399,7 @@ index 51471e51d..21b28ea45 100644 const SmartcardTokenIface = ` diff --git a/js/gdm/util.js b/js/gdm/util.js -index 14d581714..ec0a6f84d 100644 +index 44795129e..5d5618c77 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -12,7 +12,7 @@ import * as Vmware from './vmware.js'; @@ -5448,7 +5448,7 @@ index 44b871502..e42b2974a 100644 2.55.0 -From 0aca4140bf6a8c2339fe012e0cc937d8505eeb0a Mon Sep 17 00:00:00 2001 +From 3794844d91b3cc09c271e46594a854ad680c5e84 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 10 Mar 2026 14:27:50 +0100 Subject: [PATCH 46/72] gdm/smartcardManager: Skip login_token aliases to avoid @@ -5483,7 +5483,7 @@ index 21b28ea45..98f762d7d 100644 2.55.0 -From 3117ad9977c60135501dc6dd5d481f52e0932425 Mon Sep 17 00:00:00 2001 +From 5852ce77fcb1acdcab159bcf58c06b3468318af6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 18 Aug 2025 12:08:21 +0200 Subject: [PATCH 47/72] gdm: Add AuthServices @@ -5571,7 +5571,7 @@ Part-of: create mode 100644 js/gdm/authServicesLegacy.js diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 00d6a6255..ce78914d7 100644 +index d29fc5478..0ae6611c3 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -11,6 +11,7 @@ import * as AuthList from './authList.js'; @@ -5662,13 +5662,13 @@ index 00d6a6255..ce78914d7 100644 - this.reset(); - } - -- _onShowMessage(serviceName, message, type, showMessageResolver) { -+ _onShowMessage({serviceName, message, type, showMessageResolver}) { - this.setMessage(message, type); - this.emit('prompted'); +- _onShowMessage(serviceName, message, type) { ++ _onShowMessage({serviceName, message, type}) { + let wiggleParameters = {duration: 0}; -@@ -485,13 +458,15 @@ export const AuthPrompt = GObject.registerClass({ - showMessageResolver?.(wigglePromise); + if (type === GdmUtil.MessageType.ERROR && +@@ -489,13 +462,15 @@ export const AuthPrompt = GObject.registerClass({ + } } - _onVerificationFailed(serviceName, canRetry) { @@ -5685,7 +5685,7 @@ index 00d6a6255..ce78914d7 100644 this.verificationStatus = AuthPromptStatus.VERIFYING; this._entry.text = ''; this.startPreemptiveInput(); -@@ -788,8 +763,10 @@ export const AuthPrompt = GObject.registerClass({ +@@ -794,8 +769,10 @@ export const AuthPrompt = GObject.registerClass({ this._preemptiveAnswerWatchId = this._idleMonitor.add_idle_watch(3000, this._onUserStoppedTypePreemptiveAnswer.bind(this)); @@ -5698,7 +5698,7 @@ index 00d6a6255..ce78914d7 100644 reuseEntryText = reuseEntryText || !!this._preemptiveAnswer || this._preemptiveInput; -@@ -812,7 +789,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -818,7 +795,7 @@ export const AuthPrompt = GObject.registerClass({ if (oldStatus === AuthPromptStatus.VERIFICATION_CANCELLED) return; resetType = ResetType.PROVIDE_USERNAME; @@ -5707,7 +5707,7 @@ index 00d6a6255..ce78914d7 100644 // We don't need to know the username if the user preempted the login screen // with a smartcard or with preauthenticated oVirt credentials resetType = ResetType.DONT_PROVIDE_USERNAME; -@@ -849,7 +826,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -855,7 +832,8 @@ export const AuthPrompt = GObject.registerClass({ if (!this._preemptiveInput) this.updateSensitivity({sensitive: false}); @@ -6579,7 +6579,7 @@ index 000000000..ac2dcfb44 + } +} diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index cdb64d322..61e671199 100644 +index e0cd0555a..2398cfda2 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -1106,7 +1106,7 @@ export const LoginDialog = GObject.registerClass({ @@ -6592,7 +6592,7 @@ index cdb64d322..61e671199 100644 sectionName: _PRIMARY_LOGIN_METHOD_SECTION_NAME, }); diff --git a/js/gdm/util.js b/js/gdm/util.js -index ec0a6f84d..97c2fdde0 100644 +index 5d5618c77..31478dd00 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -1,24 +1,14 @@ @@ -6866,7 +6866,7 @@ index ec0a6f84d..97c2fdde0 100644 if (!this.hasPendingMessages) return; -@@ -298,12 +274,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -303,12 +279,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { return this._messageQueue.some(m => m.serviceName === serviceName); } @@ -6880,22 +6880,21 @@ index ec0a6f84d..97c2fdde0 100644 + this._queuePriorityMessage({serviceName, messageType}); } - async _queueMessageTimeout() { -@@ -314,7 +290,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { - const {promise, resolve} = Promise.withResolvers(); - this._showMessageResolver = resolve; + _queueMessageTimeout() { +@@ -318,7 +294,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { + const message = this.currentMessage; -- this.emit('show-message', message.serviceName, message.text, message.type, this._showMessageResolver); + delete this._currentMessageExtraInterval; +- this.emit('show-message', message.serviceName, message.text, message.type); + this.emit('show-message', { + serviceName: message.serviceName, + message: message.text, + type: message.type, -+ showMessageResolver: this._showMessageResolver, + }); - await promise.catch(logError); - if (!this._showMessageResolver) -@@ -329,7 +310,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + message.interval + (this._currentMessageExtraInterval | 0), () => { +@@ -328,7 +308,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._messageQueue.shift(); this._queueMessageTimeout(); } else { @@ -6904,7 +6903,7 @@ index ec0a6f84d..97c2fdde0 100644 } return GLib.SOURCE_REMOVE; -@@ -337,14 +318,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -336,14 +316,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout'); } @@ -6922,7 +6921,7 @@ index ec0a6f84d..97c2fdde0 100644 const newQueue = this._messageQueue.filter(m => { if (m.serviceName !== serviceName || m.type >= messageType) return m.text !== message; -@@ -355,11 +336,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -354,483 +334,165 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._clearMessageQueue(); this._messageQueue = newQueue; @@ -6936,26 +6935,20 @@ index ec0a6f84d..97c2fdde0 100644 if (this._messageQueueTimeoutId !== 0) { GLib.source_remove(this._messageQueueTimeoutId); -@@ -371,473 +352,154 @@ export class ShellUserVerifier extends Signals.EventEmitter { - this._showMessageResolver = null; + this._messageQueueTimeoutId = 0; } - - this.emit('show-message', null, null, MessageType.NONE); -+ this.emit('show-message', {type: MessageType.NONE}); - } - +- } +- - async _initFingerprintManager() { - if (this._fingerprintManager) - return; -+ _reportInitError(initError) { -+ const {cause, message, serviceName} = initError; - this._fingerprintManager = FingerprintManager.getFingerprintManager(); - this._fingerprintManager.connectObject( - 'reader-type-changed', () => this._onFingerprintReaderTypeChanged(), - this); -+ logError(cause, message); - +- - if (!this._getDetectedDefaultService()) { - // Other authentication methods would have already been detected by - // now as possibilities if they were available. @@ -6967,34 +6960,7 @@ index ec0a6f84d..97c2fdde0 100644 - // we should fail early without having the shell to misbehave - this._fingerprintManager.setDefaultTimeout(FINGERPRINT_SERVICE_PROXY_TIMEOUT); - await this._fingerprintManager.checkReaderType(this._cancellable); -+ this._queueMessage({ -+ serviceName, -+ message: _('Authentication error'), -+ messageType: MessageType.ERROR, -+ }); -+ this._verificationFailed({serviceName}); -+ } -+ -+ async _getUserVerifierProxies(userName, cancellable) { -+ const proxies = {}; -+ -+ if (userName) { -+ try { -+ proxies.userVerifier = await this._client.open_reauthentication_channel( -+ userName, cancellable); -+ } catch (e) { -+ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) -+ throw e; -+ if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) && -+ !this._reauthOnly) { -+ // Gdm emits org.freedesktop.DBus.Error.AccessDenied when there -+ // is no session to reauthenticate. Fall back to performing -+ // verification from this login session -+ return this._getUserVerifierProxies(null, cancellable); -+ } -+ throw new InitError(e, 'Failed to open reauthentication channel'); -+ } - } else { +- } else { - // Ensure fingerprint service starts, but do not wait for it - this._fingerprintManager.checkReaderType(this._cancellable); - } @@ -7013,8 +6979,9 @@ index ec0a6f84d..97c2fdde0 100644 - _onCredentialManagerAuthenticated(credentialManager, _token) { - this._preemptingService = credentialManager.service; - this.emit('credential-manager-authenticated'); -- } -- ++ this.emit('show-message', {type: MessageType.NONE}); + } + - _initSmartcardManager() { - if (this._smartcardManager) - return; @@ -7034,10 +7001,13 @@ index ec0a6f84d..97c2fdde0 100644 - 'smartcard-inserted', () => this._checkForSmartcard(), - 'smartcard-removed', () => this._checkForSmartcard(), this); - } -- ++ _reportInitError(initError) { ++ const {cause, message, serviceName} = initError; + - _checkForSmartcard() { - let smartcardDetected; -- ++ logError(cause, message); + - if (!this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY)) - smartcardDetected = false; - else if (this._reauthOnly) @@ -7085,6 +7055,34 @@ index ec0a6f84d..97c2fdde0 100644 - // verification from this login session - this._getUserVerifier(); - return; ++ this._queueMessage({ ++ serviceName, ++ message: _('Authentication error'), ++ messageType: MessageType.ERROR, ++ }); ++ this._verificationFailed({serviceName}); ++ } ++ ++ async _getUserVerifierProxies(userName, cancellable) { ++ const proxies = {}; ++ ++ if (userName) { ++ try { ++ proxies.userVerifier = await this._client.open_reauthentication_channel( ++ userName, cancellable); ++ } catch (e) { ++ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) ++ throw e; ++ if (e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) && ++ !this._reauthOnly) { ++ // Gdm emits org.freedesktop.DBus.Error.AccessDenied when there ++ // is no session to reauthenticate. Fall back to performing ++ // verification from this login session ++ return this._getUserVerifierProxies(null, cancellable); ++ } ++ throw new InitError(e, 'Failed to open reauthentication channel'); ++ } ++ } else { + try { + proxies.userVerifier = await this._client.get_user_verifier( + cancellable); @@ -7241,12 +7239,23 @@ index ec0a6f84d..97c2fdde0 100644 - return Constants.FINGERPRINT_SERVICE_NAME; - return null; - } -+ _updateAuthServices() { -+ const enabledRoles = []; - +- - _updateDefaultService() { - const oldDefaultService = this._defaultService; - this._defaultService = this._getDetectedDefaultService(); +- +- if (!this._defaultService) { +- log('no authentication service is enabled, using password authentication'); +- this._defaultService = Constants.PASSWORD_SERVICE_NAME; +- } ++ _updateAuthServices() { ++ const enabledRoles = []; + +- if (oldDefaultService && +- oldDefaultService !== this._defaultService && +- this._activeServices.has(oldDefaultService)) +- this._cancelAndReset(); +- } + if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY)) + enabledRoles.push(Constants.PASSWORD_ROLE_NAME); + if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY)) @@ -7254,17 +7263,6 @@ index ec0a6f84d..97c2fdde0 100644 + if (this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY)) + enabledRoles.push(Constants.FINGERPRINT_ROLE_NAME); -- if (!this._defaultService) { -- log('no authentication service is enabled, using password authentication'); -- this._defaultService = Constants.PASSWORD_SERVICE_NAME; -- } -- -- if (oldDefaultService && -- oldDefaultService !== this._defaultService && -- this._activeServices.has(oldDefaultService)) -- this._cancelAndReset(); -- } -- - async _startService(serviceName) { - this._hold?.acquire(); - try { @@ -7296,24 +7294,25 @@ index ec0a6f84d..97c2fdde0 100644 - } - this._hold?.release(); - } -- + - _beginVerification() { - this._startService(this._getForegroundService()); - this._maybeStartFingerprintVerification().catch(logError); - } -- ++ this._enabledRoles = enabledRoles; + - async _maybeStartFingerprintVerification() { - if (this._userName && - this._fingerprintReaderFound && - !this.serviceIsForeground(Constants.FINGERPRINT_SERVICE_NAME)) - await this._startService(Constants.FINGERPRINT_SERVICE_NAME); -- } ++ this._createAuthServices(); + } - _onChoiceListQuery(client, serviceName, promptMessage, list) { - if (!this.serviceIsForeground(serviceName)) - return; -+ this._enabledRoles = enabledRoles; - +- - const choiceList = {}; - for (const [key, value] of Object.entries(list.deepUnpack())) - choiceList[key] = {title: value}; @@ -7340,9 +7339,8 @@ index ec0a6f84d..97c2fdde0 100644 - MessageType.HINT); - } - } -+ this._createAuthServices(); - } - +- } +- - _onProblem(client, serviceName, problem) { - const isFingerprint = this.serviceIsFingerprint(serviceName); + _createAuthServices() { @@ -7513,7 +7511,7 @@ index ec0a6f84d..97c2fdde0 100644 } } -@@ -856,47 +518,4 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -849,47 +511,4 @@ export class ShellUserVerifier extends Signals.EventEmitter { }); }); } @@ -7604,7 +7602,7 @@ index ee0829c96..7f534c75f 100644 2.55.0 -From c95867ff2c518df0414a6b9668ec83d3cbef57a4 Mon Sep 17 00:00:00 2001 +From de131589214b56519ef95cf271cfa65abb7dff0f Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 16 Feb 2026 12:21:54 +0100 Subject: [PATCH 48/72] gdm: Add fingerprint ready state to delay showing icon @@ -7729,7 +7727,7 @@ index ac2dcfb44..1c1cce1e4 100644 2.55.0 -From e2af995e18e082d8e3e4ac2c6f0afb2fc517b81f Mon Sep 17 00:00:00 2001 +From 96d18ce5e9ae7a40ffa705c146b2c6dc96ff1edb Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 6 Feb 2024 14:09:34 -0500 Subject: [PATCH 49/72] gdm: Add authServicesSSSDSwitchable @@ -7965,7 +7963,7 @@ index 000000000..04e97b076 + } +} diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 61e671199..6d0708b1f 100644 +index 2398cfda2..a9128ed34 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -453,7 +453,10 @@ export const LoginDialog = GObject.registerClass({ @@ -7981,7 +7979,7 @@ index 61e671199..6d0708b1f 100644 } diff --git a/js/gdm/util.js b/js/gdm/util.js -index 97c2fdde0..d5bac9c6a 100644 +index 31478dd00..ef0d0b506 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -9,6 +9,7 @@ import * as Main from '../ui/main.js'; @@ -8072,7 +8070,7 @@ index 97c2fdde0..d5bac9c6a 100644 this._authServicesLegacy?.answerQuery(serviceName, answer); } -@@ -428,10 +443,15 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -421,10 +436,15 @@ export class ShellUserVerifier extends Signals.EventEmitter { if (this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY)) enabledRoles.push(Constants.FINGERPRINT_ROLE_NAME); @@ -8089,7 +8087,7 @@ index 97c2fdde0..d5bac9c6a 100644 this._createAuthServices(); } -@@ -445,19 +465,25 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -438,19 +458,25 @@ export class ShellUserVerifier extends Signals.EventEmitter { allowedFailures: this.allowedFailures, reauthOnly: this._reauthOnly, }; @@ -8116,7 +8114,7 @@ index 97c2fdde0..d5bac9c6a 100644 this._authServicesLegacy, ].forEach(authServices => { authServices?.connectObject( -@@ -481,11 +507,15 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -474,11 +500,15 @@ export class ShellUserVerifier extends Signals.EventEmitter { } get selectedMechanism() { @@ -8189,7 +8187,7 @@ index 7f534c75f..f0e1aed6e 100644 2.55.0 -From dd6723b0307b61000b21558cc0b9935ef5d29491 Mon Sep 17 00:00:00 2001 +From 2d3da8d24fae0f4ca5f7a2144812bfa03b32ac8f Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 12 Nov 2025 17:25:33 +0100 Subject: [PATCH 50/72] authServicesSSSDSwitchable: Allow resetting expired @@ -8273,7 +8271,7 @@ index 04e97b076..e8b2e9620 100644 2.55.0 -From 286d3b30f6535fcbaf33c11f34cbbc8575550763 Mon Sep 17 00:00:00 2001 +From 56a6a27a8d9c24f8a9726201104515ad9de60767 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 21 Aug 2025 22:25:02 +0200 Subject: [PATCH 51/72] gdm: Allow starting authServicesLegacy as fallback @@ -8536,7 +8534,7 @@ index e8b2e9620..2a08be1f0 100644 const {serviceName, prompt} = this._selectedMechanism; diff --git a/js/gdm/util.js b/js/gdm/util.js -index d5bac9c6a..faf835cc9 100644 +index ef0d0b506..5d062d5f8 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -211,6 +211,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { @@ -8551,7 +8549,7 @@ index d5bac9c6a..faf835cc9 100644 this._clearMessageQueue(); this._cancellable?.cancel(); -@@ -466,10 +471,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -459,10 +464,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { reauthOnly: this._reauthOnly, }; if (this._switchableAuthenticationEnabled && @@ -8568,7 +8566,7 @@ index d5bac9c6a..faf835cc9 100644 this._connectAuthServices(); } -@@ -513,9 +522,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -506,9 +515,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { } _onMechanismsChanged() { @@ -8583,7 +8581,7 @@ index d5bac9c6a..faf835cc9 100644 const selectedMechanism = this.selectedMechanism ?? mechanisms.find(m => isSelectable(m)) ?? -@@ -524,6 +536,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -517,6 +529,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { this.emit('mechanisms-changed', {mechanisms, selectedMechanism}); } @@ -8602,7 +8600,7 @@ index d5bac9c6a..faf835cc9 100644 2.55.0 -From fd329502f09901a04c53fb86e3a7ff9e6d7ef791 Mon Sep 17 00:00:00 2001 +From f03ee0604da0ac35e95a805dcebdab9bb9d93204 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 11 Feb 2026 03:36:54 +0100 Subject: [PATCH 52/72] ui/qrCode: Add a QR Code widget @@ -8826,7 +8824,7 @@ index 000000000..caf0999f3 2.55.0 -From 8451bf466001cdac9616fae76365632c08cd7d56 Mon Sep 17 00:00:00 2001 +From 184692b0d7657a74bc5902df8662a475ef7e900d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 20 Jul 2026 19:47:32 +0200 Subject: [PATCH 53/72] authPrompt: Support show button @@ -8879,7 +8877,7 @@ index 572ce9f59..318962df8 100644 // a.k.a. the lockscreen, uses transparent styles .unlock-dialog { diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index ce78914d7..75f8d4177 100644 +index 0ae6611c3..90bcc9501 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -87,6 +87,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -8907,7 +8905,7 @@ index ce78914d7..75f8d4177 100644 // center elements inside _mainBox between the cancel // button on the left and this spacer on the right this._mainBox.add_child(new Clutter.Actor({ -@@ -443,7 +454,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -456,12 +467,34 @@ export const AuthPrompt = GObject.registerClass({ if (message && type < GdmUtil.MessageType.ERROR && !this._entryArea.visible && @@ -8917,8 +8915,6 @@ index ce78914d7..75f8d4177 100644 this._fadeInElement(this._entryArea); this.updateSensitivity({sensitive: true}); } -@@ -458,6 +470,27 @@ export const AuthPrompt = GObject.registerClass({ - showMessageResolver?.(wigglePromise); } + _onShowButton({serviceName, label, callback}) { @@ -8945,7 +8941,7 @@ index ce78914d7..75f8d4177 100644 _onVerificationFailed({serviceName, canRetry}) { const wasQueryingService = this._queryingService === serviceName; -@@ -579,6 +612,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -583,6 +616,7 @@ export const AuthPrompt = GObject.registerClass({ this._authListTitle.child.text = ''; this._authList.clear(); this._authList.hide(); @@ -8953,7 +8949,7 @@ index ce78914d7..75f8d4177 100644 this._mainBox.opacity = 255; this._mainBox.reactive = true; -@@ -593,6 +627,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -597,6 +631,7 @@ export const AuthPrompt = GObject.registerClass({ this._entry.hint_text = question; this._authList.hide(); @@ -8961,7 +8957,7 @@ index ce78914d7..75f8d4177 100644 this._fadeInElement(this._entryArea); this.updateSensitivity({sensitive: true}); -@@ -677,6 +712,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -683,6 +718,7 @@ export const AuthPrompt = GObject.registerClass({ const authWidget = [ this._authList, @@ -8987,10 +8983,10 @@ index 28a07558d..fc7861de6 100644 }; diff --git a/js/gdm/util.js b/js/gdm/util.js -index faf835cc9..8611cb090 100644 +index 5d062d5f8..4e26ea397 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -505,6 +505,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -498,6 +498,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { 'verification-complete', () => this.emit('verification-complete'), 'reset', (_, args) => this.emit('reset', args), 'show-choice-list', (_, args) => this.emit('show-choice-list', args), @@ -9021,7 +9017,7 @@ index f0e1aed6e..fc90886d5 100644 2.55.0 -From 93ef9ce43f2f7690f9b5d8a720e36c1fe5f2a695 Mon Sep 17 00:00:00 2001 +From de105ed9631e458d0d6b028483953e0eddbc6c2b Mon Sep 17 00:00:00 2001 From: Ray Strode Date: Tue, 6 Feb 2024 14:18:24 -0500 Subject: [PATCH 54/72] gdm: Add support for Web Login in @@ -9146,7 +9142,7 @@ index 318962df8..04f24a789 100644 } diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 75f8d4177..afc5e0f00 100644 +index 90bcc9501..b89152e4f 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -15,6 +15,7 @@ import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; @@ -9184,7 +9180,7 @@ index 75f8d4177..afc5e0f00 100644 // center elements inside _mainBox between the cancel // button on the left and this spacer on the right this._mainBox.add_child(new Clutter.Actor({ -@@ -455,7 +469,8 @@ export const AuthPrompt = GObject.registerClass({ +@@ -468,7 +482,8 @@ export const AuthPrompt = GObject.registerClass({ type < GdmUtil.MessageType.ERROR && !this._entryArea.visible && !this._authList.visible && @@ -9194,7 +9190,7 @@ index 75f8d4177..afc5e0f00 100644 this._fadeInElement(this._entryArea); this.updateSensitivity({sensitive: true}); } -@@ -491,6 +506,47 @@ export const AuthPrompt = GObject.registerClass({ +@@ -495,6 +510,47 @@ export const AuthPrompt = GObject.registerClass({ this.emit('prompted'); } @@ -9242,7 +9238,7 @@ index 75f8d4177..afc5e0f00 100644 _onVerificationFailed({serviceName, canRetry}) { const wasQueryingService = this._queryingService === serviceName; -@@ -517,11 +573,13 @@ export const AuthPrompt = GObject.registerClass({ +@@ -521,11 +577,13 @@ export const AuthPrompt = GObject.registerClass({ this.stopSpinning({animate: true}); this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED; @@ -9261,7 +9257,7 @@ index 75f8d4177..afc5e0f00 100644 }); this.emit('verification-complete'); -@@ -593,6 +651,9 @@ export const AuthPrompt = GObject.registerClass({ +@@ -597,6 +655,9 @@ export const AuthPrompt = GObject.registerClass({ stopSpinning({animate = false} = {}) { this.emit('loading', false); this.setActorInDefaultButtonWell(this._nextButton, animate); @@ -9271,7 +9267,7 @@ index 75f8d4177..afc5e0f00 100644 } clear(params) { -@@ -613,9 +674,12 @@ export const AuthPrompt = GObject.registerClass({ +@@ -617,9 +678,12 @@ export const AuthPrompt = GObject.registerClass({ this._authList.clear(); this._authList.hide(); this._authButton.hide(); @@ -9286,7 +9282,7 @@ index 75f8d4177..afc5e0f00 100644 } setQuestion(question) { -@@ -628,6 +692,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -632,6 +696,7 @@ export const AuthPrompt = GObject.registerClass({ this._authList.hide(); this._authButton.hide(); @@ -9294,7 +9290,7 @@ index 75f8d4177..afc5e0f00 100644 this._fadeInElement(this._entryArea); this.updateSensitivity({sensitive: true}); -@@ -713,6 +778,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -719,6 +784,7 @@ export const AuthPrompt = GObject.registerClass({ const authWidget = [ this._authList, this._authButton, @@ -9489,7 +9485,7 @@ index 2b6061578..c3b790325 100644 export const PASSWORD_SERVICE_NAME = 'gdm-password'; export const SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; diff --git a/js/gdm/util.js b/js/gdm/util.js -index 8611cb090..815af4482 100644 +index 4e26ea397..9e9666452 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -18,6 +18,7 @@ export const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication'; @@ -9508,7 +9504,7 @@ index 8611cb090..815af4482 100644 return true; case Constants.FINGERPRINT_ROLE_NAME: return false; -@@ -447,6 +449,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -440,6 +442,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { enabledRoles.push(Constants.SMARTCARD_ROLE_NAME); if (this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY)) enabledRoles.push(Constants.FINGERPRINT_ROLE_NAME); @@ -9517,7 +9513,7 @@ index 8611cb090..815af4482 100644 const switchableAuthentication = this._settings.get_boolean(SWITCHABLE_AUTHENTICATION_KEY); -@@ -507,6 +511,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -500,6 +504,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { 'show-choice-list', (_, args) => this.emit('show-choice-list', args), 'show-button', (_, args) => this.emit('show-button', args), 'mechanisms-changed', () => this._onMechanismsChanged(), @@ -9861,7 +9857,7 @@ index fc90886d5..08c23cbff 100644 2.55.0 -From 87023c539945e0ef62befe9976c3b460e046e4c6 Mon Sep 17 00:00:00 2001 +From 0ce7bee2c37f8d8384040a350a15421146c29bd7 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 14 Jan 2025 07:31:59 -0500 Subject: [PATCH 55/72] gdm: Add support for Smartcard in @@ -10029,7 +10025,7 @@ index a321f4489..668637db0 100644 2.55.0 -From d870c1ef3359a6db913c76f050b86eadbca2419f Mon Sep 17 00:00:00 2001 +From e9ee7182088bbfcc9c17ab1dc43d8f4e771e0a69 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 15 Sep 2025 16:36:42 +0200 Subject: [PATCH 56/72] gdm: Add support for Passkey in @@ -10223,7 +10219,7 @@ index c3b790325..a829d9866 100644 export const PASSWORD_SERVICE_NAME = 'gdm-password'; diff --git a/js/gdm/util.js b/js/gdm/util.js -index 815af4482..605b0950f 100644 +index 9e9666452..578c6a692 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -17,6 +17,7 @@ export const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen'; @@ -10242,7 +10238,7 @@ index 815af4482..605b0950f 100644 case Constants.WEB_LOGIN_ROLE_NAME: return true; case Constants.FINGERPRINT_ROLE_NAME: -@@ -447,6 +449,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -440,6 +442,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { enabledRoles.push(Constants.PASSWORD_ROLE_NAME); if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY)) enabledRoles.push(Constants.SMARTCARD_ROLE_NAME); @@ -10268,7 +10264,7 @@ index 84cd0fb08..d8d825da6 100644 2.55.0 -From b2292cc9bc6c61d40626edac89d18b9f974dd4b2 Mon Sep 17 00:00:00 2001 +From 4eab7036fecf0ace0f787e5ecb017fa890c32069 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 8 Jul 2026 20:01:04 +0200 Subject: [PATCH 57/72] gdm/util: Generalize authServices orchestration @@ -10380,7 +10376,7 @@ index c37ca3890..ee018e7b9 100644 _handleReset() { diff --git a/js/gdm/util.js b/js/gdm/util.js -index 605b0950f..f7abecbfe 100644 +index 578c6a692..4b1099a6e 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -18,7 +18,6 @@ export const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication'; @@ -10524,7 +10520,7 @@ index 605b0950f..f7abecbfe 100644 } _getIntervalForMessage(message) { -@@ -456,15 +453,16 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -449,15 +446,16 @@ export class ShellUserVerifier extends Signals.EventEmitter { if (this._settings.get_boolean(WEB_AUTHENTICATION_KEY)) enabledRoles.push(Constants.WEB_LOGIN_ROLE_NAME); @@ -10545,7 +10541,7 @@ index 605b0950f..f7abecbfe 100644 this._createAuthServices(); } -@@ -474,36 +472,34 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -467,36 +465,34 @@ export class ShellUserVerifier extends Signals.EventEmitter { const params = { client: this._client, @@ -10599,7 +10595,7 @@ index 605b0950f..f7abecbfe 100644 'ask-question', (_, args) => this.emit('ask-question', args), 'queue-message', (_, args) => this._queueMessage(args), 'queue-priority-message', (_, args) => this._queuePriorityMessage(args), -@@ -526,18 +522,40 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -519,18 +515,40 @@ export class ShellUserVerifier extends Signals.EventEmitter { } get selectedMechanism() { @@ -10647,7 +10643,7 @@ index 605b0950f..f7abecbfe 100644 const selectedMechanism = this.selectedMechanism ?? mechanisms.find(m => isSelectable(m)) ?? -@@ -546,14 +564,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -539,14 +557,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { this.emit('mechanisms-changed', {mechanisms, selectedMechanism}); } @@ -10666,7 +10662,7 @@ index 605b0950f..f7abecbfe 100644 2.55.0 -From 3aae91592504fba330f5d63ec3f1739eac1138b4 Mon Sep 17 00:00:00 2001 +From b63bc27b1d5e9c7b0a062a6c5511682451a131e6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Sun, 19 Jul 2026 13:31:48 +0200 Subject: [PATCH 58/72] gdm: Fix auth roles enablement by settings @@ -10870,7 +10866,7 @@ index ee018e7b9..a88e971d3 100644 _handleReset() { diff --git a/js/gdm/util.js b/js/gdm/util.js -index f7abecbfe..301dcd0f8 100644 +index 4b1099a6e..be24ceeaf 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -14,11 +14,6 @@ import {AuthServicesSSSDSwitchable} from './authServicesSSSDSwitchable.js'; @@ -10885,7 +10881,7 @@ index f7abecbfe..301dcd0f8 100644 export const BANNER_MESSAGE_KEY = 'banner-message-enable'; export const BANNER_MESSAGE_SOURCE_KEY = 'banner-message-source'; export const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text'; -@@ -440,30 +435,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -433,30 +428,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { } _updateAuthServices() { @@ -10917,7 +10913,7 @@ index f7abecbfe..301dcd0f8 100644 this._createAuthServices(); } -@@ -474,21 +453,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -467,21 +446,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { client: this._client, allowedFailures: this.allowedFailures, reauthOnly: this._reauthOnly, @@ -10944,7 +10940,7 @@ index f7abecbfe..301dcd0f8 100644 this._connectAuthServices(); } -@@ -532,13 +504,13 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -525,13 +497,13 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._redistributingRoles = true; @@ -10964,7 +10960,7 @@ index f7abecbfe..301dcd0f8 100644 2.55.0 -From 174ab6cda1c291f62f5311147188b98ef0f53ab8 Mon Sep 17 00:00:00 2001 +From fbee5d5f08dc3554fa55c236367bf10a2a7d051e Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Sun, 19 Jul 2026 15:25:00 +0200 Subject: [PATCH 59/72] gdm: Centralize role properties in authServices base @@ -10999,7 +10995,7 @@ Part-of: 6 files changed, 39 insertions(+), 68 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index afc5e0f00..3beb04f4d 100644 +index b89152e4f..01a714ba9 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -9,7 +9,6 @@ import St from 'gi://St'; @@ -11010,7 +11006,7 @@ index afc5e0f00..3beb04f4d 100644 import * as GdmUtil from './util.js'; import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; import * as Params from '../misc/params.js'; -@@ -555,7 +554,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -559,7 +558,7 @@ export const AuthPrompt = GObject.registerClass({ // Only allow instant retrying with password authentication. // The rest of authentications will retry through the reset flow. @@ -11086,7 +11082,7 @@ index f98000c35..a09e2751b 100644 this.emit('reset', {softReset: true}); } diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 6d0708b1f..638fb3c54 100644 +index a9128ed34..d02ad45bc 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -1118,7 +1118,7 @@ export const LoginDialog = GObject.registerClass({ @@ -11099,7 +11095,7 @@ index 6d0708b1f..638fb3c54 100644 sectionName: _PRIMARY_LOGIN_METHOD_SECTION_NAME, ...m, diff --git a/js/gdm/util.js b/js/gdm/util.js -index 301dcd0f8..5cc77a26c 100644 +index be24ceeaf..7dc09feaa 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -99,42 +99,6 @@ export function cloneAndFadeOutActor(actor) { @@ -11145,7 +11141,7 @@ index 301dcd0f8..5cc77a26c 100644 export class ShellUserVerifier extends Signals.EventEmitter { constructor(client, params) { super(); -@@ -530,7 +494,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -523,7 +487,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { .filter(m => !seenRoles.has(m.role) && seenRoles.add(m.role)); const selectedMechanism = this.selectedMechanism ?? @@ -11242,7 +11238,7 @@ index d8d825da6..68331934d 100644 2.55.0 -From b1505b00570555e2d6f214eb2f921d12196517ca Mon Sep 17 00:00:00 2001 +From ec6e84452785b8c6ed5fad7c279768247d69500a Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Sun, 19 Jul 2026 15:35:40 +0200 Subject: [PATCH 60/72] gdm: Rename passkeyDeviceManager to fido2TokenManager @@ -11508,7 +11504,7 @@ index ced2f28e2..7d5f4b039 100644 2.55.0 -From a65ee4a7d1ca1952b7aebfec9cb90734ad8e973a Mon Sep 17 00:00:00 2001 +From 7e8207cf5d88a031fefcfd49bbfbcf950b23d5e2 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 20 Jul 2026 19:28:48 +0200 Subject: [PATCH 61/72] gdm: Move device setups to authServices subclasses @@ -11772,7 +11768,7 @@ index ecba7d87a..d261d0012 100644 2.55.0 -From 422c6fec320512ad36203018aa5d0e8d7c51addf Mon Sep 17 00:00:00 2001 +From ef9af59674e59b0693d03792eded0a8a22fb4817 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 20 Jul 2026 20:02:22 +0200 Subject: [PATCH 62/72] gdm: Remove constants module and add wiggle parameter @@ -11795,32 +11791,27 @@ Part-of: js/gdm/constants.js | 10 ----- js/gdm/util.js | 21 ++++----- js/js-resources.gresource.xml | 1 - - 7 files changed, 97 insertions(+), 95 deletions(-) + 7 files changed, 98 insertions(+), 94 deletions(-) delete mode 100644 js/gdm/constants.js diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 3beb04f4d..0ba1a5de6 100644 +index 01a714ba9..6ee6bd3e5 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js -@@ -458,7 +458,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -458,11 +458,10 @@ export const AuthPrompt = GObject.registerClass({ this.emit('prompted'); } -- _onShowMessage({serviceName, message, type, showMessageResolver}) { -+ _onShowMessage({message, type, shouldWiggle, showMessageResolver}) { - this.setMessage(message, type); - this.emit('prompted'); +- _onShowMessage({serviceName, message, type}) { ++ _onShowMessage({message, type, shouldWiggle}) { + let wiggleParameters = {duration: 0}; -@@ -474,9 +474,6 @@ export const AuthPrompt = GObject.registerClass({ - this.updateSensitivity({sensitive: true}); - } - -- const shouldWiggle = type === GdmUtil.MessageType.ERROR && -- this._userVerifier.serviceIsFingerprint(serviceName); -- - const wigglePromise = shouldWiggle - ? wiggle(this._message, {duration: 65, wiggleCount: 3}) - : Promise.resolve(); +- if (type === GdmUtil.MessageType.ERROR && +- this._userVerifier.serviceIsFingerprint(serviceName)) { ++ if (shouldWiggle) { + // TODO: Use Await for wiggle to be over before unfreezing the user verifier queue + wiggleParameters = { + duration: 65, diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index b22208a2a..3b58f4957 100644 --- a/js/gdm/authServices.js @@ -12345,7 +12336,7 @@ index a829d9866..000000000 -export const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; -export const SWITCHABLE_AUTH_SERVICE_NAME = 'gdm-switchable-auth'; diff --git a/js/gdm/util.js b/js/gdm/util.js -index 5cc77a26c..7fcb8df32 100644 +index 7dc09feaa..2821f2bb0 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -4,7 +4,6 @@ import GLib from 'gi://GLib'; @@ -12356,18 +12347,18 @@ index 5cc77a26c..7fcb8df32 100644 import * as Main from '../ui/main.js'; import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; import * as Params from '../misc/params.js'; -@@ -271,9 +270,9 @@ export class ShellUserVerifier extends Signals.EventEmitter { - this._showMessageResolver = resolve; +@@ -275,9 +274,9 @@ export class ShellUserVerifier extends Signals.EventEmitter { + delete this._currentMessageExtraInterval; this.emit('show-message', { - serviceName: message.serviceName, message: message.text, type: message.type, + shouldWiggle: message.wiggle, - showMessageResolver: this._showMessageResolver, }); -@@ -298,14 +297,20 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, +@@ -296,14 +295,20 @@ export class ShellUserVerifier extends Signals.EventEmitter { GLib.Source.set_name_by_id(this._messageQueueTimeoutId, '[gnome-shell] this._queueMessageTimeout'); } @@ -12391,7 +12382,7 @@ index 5cc77a26c..7fcb8df32 100644 const newQueue = this._messageQueue.filter(m => { if (m.serviceName !== serviceName || m.type >= messageType) return m.text !== message; -@@ -316,7 +321,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -314,7 +319,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { this._clearMessageQueue(); this._messageQueue = newQueue; @@ -12400,7 +12391,7 @@ index 5cc77a26c..7fcb8df32 100644 } _clearMessageQueue() { -@@ -390,10 +395,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -383,10 +388,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { return proxies; } @@ -12427,7 +12418,7 @@ index 7d5f4b039..0359f6028 100644 2.55.0 -From 4184d4760cedd2ec321969964b525a785ce46a76 Mon Sep 17 00:00:00 2001 +From f75b16958b106fde5b8131cd96e778a18868423a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Wed, 11 Sep 2024 02:09:57 +0200 Subject: [PATCH 63/72] gdm: Bind cancel button visibility to @@ -12445,7 +12436,7 @@ Part-of: 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 0ba1a5de6..9e27a1250 100644 +index 6ee6bd3e5..b4e913c06 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -55,6 +55,16 @@ export const AuthPrompt = GObject.registerClass({ @@ -12504,7 +12495,7 @@ index 0ba1a5de6..9e27a1250 100644 this._clearPreemptiveState(); -@@ -486,7 +495,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -492,7 +501,7 @@ export const AuthPrompt = GObject.registerClass({ this.clear(); this._queryingService = serviceName; @@ -12513,7 +12504,7 @@ index 0ba1a5de6..9e27a1250 100644 this._clearPreemptiveState(); -@@ -507,8 +516,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -513,8 +522,7 @@ export const AuthPrompt = GObject.registerClass({ this.clear(); this._queryingService = serviceName; @@ -12523,7 +12514,7 @@ index 0ba1a5de6..9e27a1250 100644 this._webLoginParams = {message, url, code, buttons}; -@@ -833,12 +841,10 @@ export const AuthPrompt = GObject.registerClass({ +@@ -841,12 +849,10 @@ export const AuthPrompt = GObject.registerClass({ if (invalidStatus.includes(this.verificationStatus)) return false; @@ -12539,7 +12530,7 @@ index 0ba1a5de6..9e27a1250 100644 return true; } -@@ -853,8 +859,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -861,8 +867,7 @@ export const AuthPrompt = GObject.registerClass({ this.verificationStatus = AuthPromptStatus.NOT_VERIFYING; if (oldStatus !== AuthPromptStatus.VERIFICATION_IN_PROGRESS) this._preemptiveAnswer = null; @@ -12549,7 +12540,7 @@ index 0ba1a5de6..9e27a1250 100644 if (this._preemptiveAnswerWatchId) this._idleMonitor.remove_watch(this._preemptiveAnswerWatchId); -@@ -948,7 +953,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -956,7 +961,7 @@ export const AuthPrompt = GObject.registerClass({ return; // If we're in a multi-step flow (step > 1), go back to step 1 instead of full reset @@ -12559,7 +12550,7 @@ index 0ba1a5de6..9e27a1250 100644 return; } diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 638fb3c54..8f51ed59f 100644 +index d02ad45bc..095dad3e7 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -503,6 +503,8 @@ export const LoginDialog = GObject.registerClass({ @@ -12585,7 +12576,7 @@ index 638fb3c54..8f51ed59f 100644 2.55.0 -From 62c4c23eb631f4a837b3ee9b7d73e47653f088ff Mon Sep 17 00:00:00 2001 +From f36287ae58f2fd95c0fc594869aa30d5d812ae0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 07:44:07 +0200 Subject: [PATCH 64/72] gdm/authServices: Make it possible for a service to @@ -12602,7 +12593,7 @@ Part-of: 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 9e27a1250..95359354a 100644 +index b4e913c06..f7571ede5 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -162,7 +162,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -12623,7 +12614,7 @@ index 9e27a1250..95359354a 100644 this._updateCancelButton(); this._mainBox.add_child(this.cancelButton); -@@ -948,6 +948,13 @@ export const AuthPrompt = GObject.registerClass({ +@@ -956,6 +956,13 @@ export const AuthPrompt = GObject.registerClass({ }); } @@ -12651,7 +12642,7 @@ index 3b58f4957..a5adea6a1 100644 this.reset(); this.clear(); diff --git a/js/gdm/util.js b/js/gdm/util.js -index 7fcb8df32..b984617f7 100644 +index 2821f2bb0..c0025f608 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -168,6 +168,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { @@ -12671,7 +12662,7 @@ index 7fcb8df32..b984617f7 100644 2.55.0 -From 454c759840aa7830a8f630f4fbf16ff0f1f8cc44 Mon Sep 17 00:00:00 2001 +From 9a6101faa37d24f3a5e84a65e66abc311b3ab8fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 07:45:12 +0200 Subject: [PATCH 65/72] gdm/authServicesSSSDSwitchable: Implement intelligent @@ -12691,7 +12682,7 @@ Part-of: 2 files changed, 113 insertions(+), 16 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 95359354a..fd9bc642b 100644 +index f7571ede5..230e5f10e 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -313,14 +313,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -12710,7 +12701,7 @@ index 95359354a..fd9bc642b 100644 this._webLoginDialog.connect('loading', () => this.emit('loading', this._webLoginDialog.isLoading)); this.add_child(this._webLoginDialog); -@@ -949,8 +942,15 @@ export const AuthPrompt = GObject.registerClass({ +@@ -957,8 +950,15 @@ export const AuthPrompt = GObject.registerClass({ } _handleCancel() { @@ -12944,7 +12935,7 @@ index cb5a62f05..439cf6a77 100644 2.55.0 -From e432b9cdbb757cedeba1d56aab1f8892e14e11cf Mon Sep 17 00:00:00 2001 +From ebeb68b4772f9dea3c0d945a663c5cab5f085acc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 07:56:47 +0200 Subject: [PATCH 66/72] gdm/authServicesSSSDSwitchable: Disable the mechanisms @@ -12978,7 +12969,7 @@ index 439cf6a77..7286ec78c 100644 2.55.0 -From 7bbf0905bdce299ea27f5ec287220b877e840450 Mon Sep 17 00:00:00 2001 +From f967fdd1cb3e4f15608ee9988463a801840fa2e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 07:58:52 +0200 Subject: [PATCH 67/72] gdm/authServicesSSSDSwitchable: Handle errors setting @@ -13016,7 +13007,7 @@ index 7286ec78c..3b462ad44 100644 2.55.0 -From e3fa3b0407c85856334938d8008fb5c16bf4bdf1 Mon Sep 17 00:00:00 2001 +From 245780b7e7d129114ae4b6343325e717f99d1dbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 08:02:46 +0200 Subject: [PATCH 68/72] gdm/util: Allow an auth service to have multiple @@ -13031,10 +13022,10 @@ Part-of: 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/js/gdm/util.js b/js/gdm/util.js -index b984617f7..5c3dc4d37 100644 +index c0025f608..d51330391 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js -@@ -497,8 +497,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -490,8 +490,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { // keeping only the first mechanism per role const seenRoles = new Set(); const mechanisms = this._authServices @@ -13055,7 +13046,7 @@ index b984617f7..5c3dc4d37 100644 2.55.0 -From e9df31ea4600d759444e4fb5ada35936e375f690 Mon Sep 17 00:00:00 2001 +From 1d998c1aa99d2a8552fbc1635f7f95fc87c721ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Mon, 27 Jul 2026 03:04:24 +0200 Subject: [PATCH 69/72] gdm: Rename util into userVerifier @@ -13083,7 +13074,7 @@ Part-of: rename js/gdm/{util.js => userVerifier.js} (100%) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index fd9bc642b..8143c2d5b 100644 +index 230e5f10e..8ff36c65b 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -9,10 +9,10 @@ import St from 'gi://St'; @@ -13107,7 +13098,7 @@ index fd9bc642b..8143c2d5b 100644 } _onDestroy() { -@@ -467,7 +467,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -479,7 +479,7 @@ export const AuthPrompt = GObject.registerClass({ // If we're showing a message and no auth widget is currently visible, // show the entry area to allow getting a preemptive answer if (message && @@ -13116,10 +13107,10 @@ index fd9bc642b..8143c2d5b 100644 !this._entryArea.visible && !this._authList.visible && !this._authButton.visible && -@@ -748,12 +748,12 @@ export const AuthPrompt = GObject.registerClass({ +@@ -754,12 +754,12 @@ export const AuthPrompt = GObject.registerClass({ } - setMessage(message, type) { + setMessage(message, type, wiggleParameters = {duration: 0}) { - if (type === GdmUtil.MessageType.ERROR) + if (type === UserVerifier.MessageType.ERROR) this._message.add_style_class_name('login-dialog-message-warning'); @@ -13264,7 +13255,7 @@ index 3b462ad44..a46b1d1d4 100644 } } diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 8f51ed59f..3b5bf7c00 100644 +index 095dad3e7..acc08e5a3 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -32,7 +32,7 @@ import * as AuthPrompt from './authPrompt.js'; @@ -13278,10 +13269,10 @@ index 8f51ed59f..3b5bf7c00 100644 import * as Main from '../ui/main.js'; diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js new file mode 100644 -index 0000000..5c3dc4d +index 0000000..d513303 --- /dev/null +++ b/js/gdm/userVerifier.js -@@ -0,0 +1,540 @@ +@@ -0,0 +1,533 @@ +import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; @@ -13539,6 +13530,11 @@ index 0000000..5c3dc4d + this.emit('no-more-messages'); + } + ++ increaseCurrentMessageTimeout(interval) { ++ if (!this._messageQueueTimeoutId && interval > 0) ++ this._currentMessageExtraInterval = interval; ++ } ++ + _serviceHasPendingMessages(serviceName) { + return this._messageQueue.some(m => m.serviceName === serviceName); + } @@ -13551,28 +13547,21 @@ index 0000000..5c3dc4d + this._queuePriorityMessage({serviceName, messageType}); + } + -+ async _queueMessageTimeout() { -+ if (this._messageQueueTimeoutId !== 0 || this._showMessageResolver) ++ _queueMessageTimeout() { ++ if (this._messageQueueTimeoutId !== 0) + return; + + const message = this.currentMessage; -+ const {promise, resolve} = Promise.withResolvers(); -+ this._showMessageResolver = resolve; + ++ delete this._currentMessageExtraInterval; + this.emit('show-message', { + message: message.text, + type: message.type, + shouldWiggle: message.wiggle, -+ showMessageResolver: this._showMessageResolver, + }); + -+ await promise.catch(logError); -+ if (!this._showMessageResolver) -+ return; -+ this._showMessageResolver = null; -+ + this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, -+ message.interval, () => { ++ message.interval + (this._currentMessageExtraInterval | 0), () => { + this._messageQueueTimeoutId = 0; + + if (this._messageQueue.length > 1) { @@ -13622,11 +13611,6 @@ index 0000000..5c3dc4d + this._messageQueueTimeoutId = 0; + } + -+ if (this._showMessageResolver) { -+ this._showMessageResolver(); -+ this._showMessageResolver = null; -+ } -+ + this.emit('show-message', {type: MessageType.NONE}); + } + @@ -13824,10 +13808,10 @@ index 0000000..5c3dc4d +} diff --git a/js/gdm/util.js b/js/gdm/util.js deleted file mode 100644 -index 5c3dc4d..0000000 +index d513303..0000000 --- a/js/gdm/util.js +++ /dev/null -@@ -1,540 +0,0 @@ +@@ -1,533 +0,0 @@ -import Clutter from 'gi://Clutter'; -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; @@ -14085,6 +14069,11 @@ index 5c3dc4d..0000000 - this.emit('no-more-messages'); - } - +- increaseCurrentMessageTimeout(interval) { +- if (!this._messageQueueTimeoutId && interval > 0) +- this._currentMessageExtraInterval = interval; +- } +- - _serviceHasPendingMessages(serviceName) { - return this._messageQueue.some(m => m.serviceName === serviceName); - } @@ -14097,28 +14086,21 @@ index 5c3dc4d..0000000 - this._queuePriorityMessage({serviceName, messageType}); - } - -- async _queueMessageTimeout() { -- if (this._messageQueueTimeoutId !== 0 || this._showMessageResolver) +- _queueMessageTimeout() { +- if (this._messageQueueTimeoutId !== 0) - return; - - const message = this.currentMessage; -- const {promise, resolve} = Promise.withResolvers(); -- this._showMessageResolver = resolve; - +- delete this._currentMessageExtraInterval; - this.emit('show-message', { - message: message.text, - type: message.type, - shouldWiggle: message.wiggle, -- showMessageResolver: this._showMessageResolver, - }); - -- await promise.catch(logError); -- if (!this._showMessageResolver) -- return; -- this._showMessageResolver = null; -- - this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, -- message.interval, () => { +- message.interval + (this._currentMessageExtraInterval | 0), () => { - this._messageQueueTimeoutId = 0; - - if (this._messageQueue.length > 1) { @@ -14168,11 +14150,6 @@ index 5c3dc4d..0000000 - this._messageQueueTimeoutId = 0; - } - -- if (this._showMessageResolver) { -- this._showMessageResolver(); -- this._showMessageResolver = null; -- } -- - this.emit('show-message', {type: MessageType.NONE}); - } - @@ -14397,7 +14374,7 @@ index 08c23cbff..34be91f7c 100644 2.55.0 -From 9cf6ab28d455c6351b7bc624e1a7bc6a7d3abe4b Mon Sep 17 00:00:00 2001 +From 3148a2e59122e1e438dcb30c3d8163b9834722fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 10:40:09 +0200 Subject: [PATCH 70/72] gdm: Move userVerifier settings and utilities to proper @@ -14494,7 +14471,7 @@ index a46b1d1d4..296691d78 100644 WAITING: 0, NOT_FOUND: 1, diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js -index 3b5bf7c00..37a0bff38 100644 +index acc08e5a3..84eddc33c 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -32,7 +32,8 @@ import * as AuthPrompt from './authPrompt.js'; @@ -14626,7 +14603,7 @@ index 000000000..bb44b0adb +export const SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication'; +export const SWITCHABLE_AUTHENTICATION_KEY = 'enable-switchable-authentication'; diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js -index 5c3dc4d37..2b7e960d3 100644 +index d51330391..1087020fd 100644 --- a/js/gdm/userVerifier.js +++ b/js/gdm/userVerifier.js @@ -1,26 +1,12 @@ @@ -14761,7 +14738,7 @@ index 271b6c0e4..daff41d6a 100644 2.55.0 -From 5b3153aec9feec615a0fbd53a292c669e27fc5d1 Mon Sep 17 00:00:00 2001 +From 61350a0680e649b18bb49b96bab45eb1c0a143b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 26 Jul 2026 10:06:35 +0200 Subject: [PATCH 71/72] gdm/authServices: Use per-request callbacks to handle @@ -14786,7 +14763,7 @@ Part-of: 5 files changed, 117 insertions(+), 79 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 8143c2d5b..007c1538c 100644 +index 8ff36c65b..4c1697f08 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -191,20 +191,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -14887,7 +14864,7 @@ index 8143c2d5b..007c1538c 100644 this.setChoiceList(promptMessage, choiceList); this.updateSensitivity({sensitive: true}); this.emit('prompted'); -@@ -492,10 +503,7 @@ export const AuthPrompt = GObject.registerClass({ +@@ -498,10 +509,7 @@ export const AuthPrompt = GObject.registerClass({ this._clearPreemptiveState(); @@ -14899,7 +14876,7 @@ index 8143c2d5b..007c1538c 100644 this._authButton.set_label(label); -@@ -670,8 +678,10 @@ export const AuthPrompt = GObject.registerClass({ +@@ -676,8 +684,10 @@ export const AuthPrompt = GObject.registerClass({ this._authListTitle.child.text = ''; this._authList.clear(); this._authList.hide(); @@ -14910,7 +14887,7 @@ index 8143c2d5b..007c1538c 100644 [this._mainBox, this._webLoginDialog].forEach(widget => { widget.opacity = 255; -@@ -695,6 +705,34 @@ export const AuthPrompt = GObject.registerClass({ +@@ -701,6 +711,34 @@ export const AuthPrompt = GObject.registerClass({ this.updateSensitivity({sensitive: true}); } @@ -15161,7 +15138,7 @@ index 296691d78..cf6a4e1fb 100644 if (pinAttempts <= 3 && pinAttempts > 0) { const message = _('You have %d attempts left. If the passkey gets locked, you may not able to access your account.').format(pinAttempts); diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js -index 2b7e960d3..183d0bed3 100644 +index 1087020fd..d68df6fb4 100644 --- a/js/gdm/userVerifier.js +++ b/js/gdm/userVerifier.js @@ -170,18 +170,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { @@ -15183,7 +15160,7 @@ index 2b7e960d3..183d0bed3 100644 addCredentialManager(serviceName, credentialManager) { this._authServices.forEach(s => s.addCredentialManager(serviceName, credentialManager)); } -@@ -468,14 +456,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -461,14 +449,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { async _waitPendingMessages({task}) { try { @@ -15204,7 +15181,7 @@ index 2b7e960d3..183d0bed3 100644 2.55.0 -From f6754a3fba6f7f6bc1985b36917d00df13e6c288 Mon Sep 17 00:00:00 2001 +From 90b5a933b33b8d53bd76bfe02523bc040436762a Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 28 Jul 2026 16:39:32 +0200 Subject: [PATCH 72/72] gdm/userVerifier: Add driver service to constrain @@ -15238,7 +15215,7 @@ index 102a22b92..d0f7659a5 100644 super(); params = Params.parse(params, { diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js -index 183d0bed3..02decbf86 100644 +index d68df6fb4..6c63a313d 100644 --- a/js/gdm/userVerifier.js +++ b/js/gdm/userVerifier.js @@ -60,6 +60,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { @@ -15265,7 +15242,7 @@ index 183d0bed3..02decbf86 100644 reset() { this._authServices.forEach(s => s.reset()); -@@ -347,9 +357,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { +@@ -340,9 +350,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { } _updateAuthServices() { diff --git a/gnome-shell.spec b/gnome-shell.spec index 4a97ef6..5a9eff8 100644 --- a/gnome-shell.spec +++ b/gnome-shell.spec @@ -40,7 +40,6 @@ Patch: disable-unlock-entry-until-question.patch Patch: 0001-main-Register-session-with-GDM-on-startup.patch Patch: 0001-loginManager-Update-RegisterSession.patch # Passwordless work -Patch: pre-changes-for-passwordless-gdm-backport.patch Patch: 0001-Support-for-web-login-and-unified-auth-mechanism.patch Patch: post-changes-for-passwordless-gdm-backport.patch diff --git a/post-changes-for-passwordless-gdm-backport.patch b/post-changes-for-passwordless-gdm-backport.patch index 98960a0..f0ee45b 100644 --- a/post-changes-for-passwordless-gdm-backport.patch +++ b/post-changes-for-passwordless-gdm-backport.patch @@ -1,7 +1,7 @@ -From 45dd4808e26dabd03c25c126e97b22a20b4bcfa5 Mon Sep 17 00:00:00 2001 +From bc94cdc84421125da2dcc5fc3d627a475bd565cc Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 2 Jun 2026 12:07:45 +0200 -Subject: [PATCH 1/5] Use Object.keys(this._sections) instead of +Subject: [PATCH 01/12] Use Object.keys(this._sections) instead of this._sections.keys() --- @@ -25,10 +25,10 @@ index 5aaa45fd3..e2c516585 100644 2.55.0 -From 2f4e4d9bff76e6b4db951890b82282cc7a01921a Mon Sep 17 00:00:00 2001 +From e1e99c9b443a60cf176d21b8538fc7f1ebd8ed65 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 2 Jun 2026 12:52:09 +0200 -Subject: [PATCH 2/5] Don't use _once timeout variants +Subject: [PATCH 02/12] Don't use _once timeout variants --- js/gdm/authServices.js | 7 +++++-- @@ -98,16 +98,15 @@ index cf6a4e1fb..0271d98f2 100644 2.55.0 -From 398fd1ad475e2092977cb210e12d3403bc0fdbaa Mon Sep 17 00:00:00 2001 +From 9927abed68a443ee9f00ddcc5e4c48187a3c70da Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Tue, 9 Jun 2026 09:57:09 +0200 -Subject: [PATCH 3/5] gdm: Use alternative to Promise.withResolvers() +Subject: [PATCH 03/12] gdm: Use alternative to Promise.withResolvers() It doesn't exist in this version --- js/gdm/authServices.js | 6 +++++- - js/gdm/userVerifier.js | 6 +++++- - 2 files changed, 10 insertions(+), 2 deletions(-) + 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index e13d4106e..e5cf21c96 100644 @@ -126,31 +125,14 @@ index e13d4106e..e5cf21c96 100644 const task = Gio.Task.new(this, cancellable, () => { try { const res = task.propagate_boolean(); -diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js -index 02decbf86..27777c6f1 100644 ---- a/js/gdm/userVerifier.js -+++ b/js/gdm/userVerifier.js -@@ -223,7 +223,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { - return; - - const message = this.currentMessage; -- const {promise, resolve} = Promise.withResolvers(); -+ let resolve, reject; -+ const promise = new Promise((res, rej) => { -+ resolve = res; -+ reject = rej; -+ }); - this._showMessageResolver = resolve; - - this.emit('show-message', { -- 2.55.0 -From dda52fc6a0e12af8dc3b6eca5f853923c311d837 Mon Sep 17 00:00:00 2001 +From 8b06c49cb2e31b26cbf155bae0795fb7c0d7d6f6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 6 Aug 2026 23:58:46 +0200 -Subject: [PATCH 4/5] gdm: Use old ButtonMask enum +Subject: [PATCH 04/12] gdm: Use old ButtonMask enum In this version it still used as ONE, TWO and THREE --- @@ -187,7 +169,7 @@ index e2c516585..ca9a0b9d1 100644 this.bind_property('reactive', this, 'can-focus', diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 007c1538c..7e69525f9 100644 +index 4c1697f08..31addc47f 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -291,7 +291,7 @@ export const AuthPrompt = GObject.registerClass({ @@ -215,10 +197,11 @@ index 3b6496296..34c371b8d 100644 -- 2.55.0 -From 5e3b6d53a6e34e27e6c38d517fe51cfe52b2b96e Mon Sep 17 00:00:00 2001 + +From 4373ce16c8653c523fcca8879915254aa76d21d0 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 7 Aug 2026 11:42:37 +0200 -Subject: [PATCH 5/5] style: Fix color styles to adapt when on light-mode +Subject: [PATCH 05/12] style: Fix color styles to adapt when on light-mode (classic-mode) --- @@ -276,3 +259,866 @@ index da04425bd..98ecf7b0f 100644 -- 2.55.0 + +From 3745870fd893ae84cde12f4a84e4bd9b2ea65762 Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 12:37:41 +0200 +Subject: [PATCH 06/12] gdm: Restore util.js and misc/smartcardManager.js as + compat shims + +Several symbols moved out of util.js into userVerifier.js and +settings.js, and smartcardManager.js moved from misc/ to gdm/. +Extensions importing from the old locations would break. + +Re-export the moved symbols from util.js, and add back +misc/smartcardManager.js as a thin re-export of the new gdm/ +location, to keep the old import paths and names working. +--- + js/gdm/util.js | 21 +++++++++++++++++++++ + js/js-resources.gresource.xml | 1 + + js/misc/smartcardManager.js | 3 +++ + 3 files changed, 25 insertions(+) + create mode 100644 js/misc/smartcardManager.js + +diff --git a/js/gdm/util.js b/js/gdm/util.js +index 10f9131d9..d9a7e2239 100644 +--- a/js/gdm/util.js ++++ b/js/gdm/util.js +@@ -3,6 +3,27 @@ import Clutter from 'gi://Clutter'; + import * as Batch from './batch.js'; + import * as Main from '../ui/main.js'; + ++// Re-exported for backward compatibility: these symbols used to live in ++// this file before being split into userVerifier.js and settings.js. ++export {MessageType, ShellUserVerifier} from './userVerifier.js'; ++export { ++ LOGIN_SCREEN_SCHEMA, ++ PASSWORD_AUTHENTICATION_KEY, ++ FINGERPRINT_AUTHENTICATION_KEY, ++ SMARTCARD_AUTHENTICATION_KEY, ++ BANNER_MESSAGE_KEY, ++ BANNER_MESSAGE_SOURCE_KEY, ++ BANNER_MESSAGE_TEXT_KEY, ++ BANNER_MESSAGE_PATH_KEY, ++ ALLOWED_FAILURES_KEY, ++ LOGO_KEY, ++ DISABLE_USER_LIST_KEY, ++} from './settings.js'; ++ ++export const PASSWORD_SERVICE_NAME = 'gdm-password'; ++export const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; ++export const SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; ++ + export const CLONE_FADE_ANIMATION_TIME = 250; + + /** +diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml +index daff41d6a..a1c0e6e3c 100644 +--- a/js/js-resources.gresource.xml ++++ b/js/js-resources.gresource.xml +@@ -50,6 +50,7 @@ + misc/permissionStore.js + misc/signals.js + misc/signalTracker.js ++ misc/smartcardManager.js + misc/systemActions.js + misc/timeLimitsManager.js + misc/util.js +diff --git a/js/misc/smartcardManager.js b/js/misc/smartcardManager.js +new file mode 100644 +index 000000000..df62ec048 +--- /dev/null ++++ b/js/misc/smartcardManager.js +@@ -0,0 +1,3 @@ ++// Re-exported for backward compatibility: this module used to live here ++// before being moved to gdm/smartcardManager.js. ++export {getSmartcardManager} from '../gdm/smartcardManager.js'; +-- +2.55.0 + + +From bd1327dfb48dc9533d6e9055e6a42f0c1c1024bf Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 12:37:50 +0200 +Subject: [PATCH 07/12] authPrompt: Restore BeginRequestType as alias for + ResetType + +ResetType was renamed from BeginRequestType. Keep the old name +exported as an alias so extensions referencing +AuthPrompt.BeginRequestType keep working. +--- + js/gdm/authPrompt.js | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js +index 31addc47f..4f7ceb86c 100644 +--- a/js/gdm/authPrompt.js ++++ b/js/gdm/authPrompt.js +@@ -44,6 +44,9 @@ export const ResetType = { + REUSE_USERNAME: 2, + }; + ++// Kept for backward compatibility: ResetType used to be named BeginRequestType. ++export const BeginRequestType = ResetType; ++ + export const AuthPrompt = GObject.registerClass({ + Signals: { + 'cancelled': {}, +-- +2.55.0 + + +From e5d4b76c4de043cb26f88065e623028970a5e1af Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 12:38:25 +0200 +Subject: [PATCH 08/12] Revert "gdm/authServices: Use per-request callbacks to + handle services queries" + +This reverts commit 929f864f1135a4225c09857ae3655d16de6c9251. + +The per-request callback pattern removed ShellUserVerifier.answerQuery() +and selectChoice() as public methods, breaking extensions that call them +directly (e.g. ShellUserVerifier subclasses used by external IdP +integrations). Restore the original answerQuery()/selectChoice() API so +those extensions keep working, at the cost of the per-request context +safety the callback pattern added. +--- + js/gdm/authPrompt.js | 82 ++++++++-------------------- + js/gdm/authServices.js | 14 ++++- + js/gdm/authServicesLegacy.js | 29 ++++------ + js/gdm/authServicesSSSDSwitchable.js | 55 +++++++------------ + js/gdm/userVerifier.js | 16 +++++- + 5 files changed, 79 insertions(+), 117 deletions(-) + +diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js +index 4f7ceb86c..bbf6c4e4e 100644 +--- a/js/gdm/authPrompt.js ++++ b/js/gdm/authPrompt.js +@@ -194,7 +194,20 @@ export const AuthPrompt = GObject.registerClass({ + + this._authList = new AuthList.AuthList(); + this._authList.hide(); +- this._authListActivateId = 0; ++ this._authList.connect('activate', (list, key) => { ++ this._authList.reactive = false; ++ this._authList.ease({ ++ opacity: 0, ++ duration: MESSAGE_FADE_OUT_ANIMATION_TIME * 0.5, ++ mode: Clutter.AnimationMode.EASE_OUT_QUAD, ++ onComplete: () => { ++ this._authListTitle.child.text = ''; ++ this._authList.clear(); ++ this._authList.hide(); ++ this._userVerifier.selectChoice(this._queryingService, key); ++ }, ++ }); ++ }); + this.add_child(this._authList); + + this._authListTitle = new St.Bin({ +@@ -300,7 +313,6 @@ export const AuthPrompt = GObject.registerClass({ + x_expand: true, + y_expand: true, + }); +- this._authButton.connect('clicked', () => this._completePendingCallback()); + this._mainBox.add_child(this._authButton); + + this._webLoginDialog = new WebLogin.WebLoginDialog(); +@@ -372,7 +384,7 @@ export const AuthPrompt = GObject.registerClass({ + this.startSpinning({animate: true}); + + if (this._queryingService) { +- this._completePendingCallback(this._entry.text); ++ this._userVerifier.answerQuery(this._queryingService, this._entry.text); + } else { + this._preemptiveAnswer = this._entry.text; + +@@ -410,37 +422,17 @@ export const AuthPrompt = GObject.registerClass({ + this._capsLockWarningLabel.visible = secret; + } + +- _setPendingCallback(callback) { +- if (this._pendingCallback) +- throw new Error('A pending request is already active'); +- this._pendingCallback = callback; +- } +- +- _completePendingCallback(...args) { +- if (!this._pendingCallback) +- throw new Error('No pending request to complete'); +- +- const callback = this._pendingCallback; +- this._pendingCallback = null; +- +- this._userVerifier.handlePendingMessages() +- .then(() => callback(...args)) +- .catch(logErrorUnlessCancelled); +- } +- +- _onAskQuestion({serviceName, question, secret, answerHandler}) { ++ _onAskQuestion({serviceName, question, secret}) { + if (this._queryingService) + this.clear(); + + this._queryingService = serviceName; + this.promptStep++; + +- this._setPendingCallback(answerHandler); +- + const preemptiveAnswer = this._preemptiveAnswer; + this._clearPreemptiveState(); + if (preemptiveAnswer) { +- this._completePendingCallback(preemptiveAnswer); ++ this._userVerifier.answerQuery(this._queryingService, preemptiveAnswer); + return; + } + +@@ -457,7 +449,7 @@ export const AuthPrompt = GObject.registerClass({ + this.emit('prompted'); + } + +- _onShowChoiceList({serviceName, promptMessage, choiceList, choiceHandler}) { ++ _onShowChoiceList({serviceName, promptMessage, choiceList}) { + if (this._queryingService) + this.clear(); + +@@ -466,9 +458,6 @@ export const AuthPrompt = GObject.registerClass({ + + this._clearPreemptiveState(); + +- this._connectAuthListActivate(); +- this._setPendingCallback(choiceHandler); +- + this.setChoiceList(promptMessage, choiceList); + this.updateSensitivity({sensitive: true}); + this.emit('prompted'); +@@ -512,7 +501,10 @@ export const AuthPrompt = GObject.registerClass({ + + this._clearPreemptiveState(); + +- this._setPendingCallback(callback); ++ const authButtonClickedId = this._authButton.connect('clicked', () => { ++ this._authButton.disconnect(authButtonClickedId); ++ callback(); ++ }); + + this._authButton.set_label(label); + +@@ -687,10 +679,8 @@ export const AuthPrompt = GObject.registerClass({ + this._authListTitle.child.text = ''; + this._authList.clear(); + this._authList.hide(); +- this._disconnectAuthListActivate(); + this._authButton.hide(); + this._closeWebLoginDialog(); +- this._pendingCallback = null; + + [this._mainBox, this._webLoginDialog].forEach(widget => { + widget.opacity = 255; +@@ -714,34 +704,6 @@ export const AuthPrompt = GObject.registerClass({ + this.updateSensitivity({sensitive: true}); + } + +- _connectAuthListActivate() { +- if (this._authListActivateId) +- return; +- +- this._authListActivateId = +- this._authList.connect('activate', (list, key) => { +- this._authList.reactive = false; +- this._authList.ease({ +- opacity: 0, +- duration: MESSAGE_FADE_OUT_ANIMATION_TIME * 0.5, +- mode: Clutter.AnimationMode.EASE_OUT_QUAD, +- onComplete: () => { +- this._authListTitle.child.text = ''; +- this._authList.clear(); +- this._authList.hide(); +- this._completePendingCallback(key); +- }, +- }); +- }); +- } +- +- _disconnectAuthListActivate() { +- if (this._authListActivateId) { +- this._authList.disconnect(this._authListActivateId); +- this._authListActivateId = 0; +- } +- } +- + _fadeInElement(element) { + if (element.visible) + return; +diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js +index e5cf21c96..e5c60e1d7 100644 +--- a/js/gdm/authServices.js ++++ b/js/gdm/authServices.js +@@ -81,7 +81,6 @@ export class AuthServices extends GObject.Object { + * @param {string} serviceName + * @param {string} question + * @param {boolean} [secret] +- * @param {Function} answerHandler + */ + 'ask-question': {param_types: [GObject.TYPE_JSOBJECT]}, + /** +@@ -93,7 +92,6 @@ export class AuthServices extends GObject.Object { + * @param {string} serviceName + * @param {string} promptMessage + * @param {object} [choiceList] - keys map to {title: string} +- * @param {Function} [choiceHandler] + */ + 'show-choice-list': {param_types: [GObject.TYPE_JSOBJECT]}, + /** +@@ -167,6 +165,14 @@ export class AuthServices extends GObject.Object { + return this._handleGetSupportedRoles(); + } + ++ selectChoice(serviceName, key) { ++ this._handleSelectChoice(serviceName, key); ++ } ++ ++ answerQuery(serviceName, answer) { ++ this._handleAnswerQuery(serviceName, answer); ++ } ++ + async beginVerification(userName, userVerifierProxies) { + this._cancellable?.cancel(); + this._cancellable = new Gio.Cancellable(); +@@ -483,6 +489,10 @@ export class AuthServices extends GObject.Object { + return this.constructor.SupportedRoles; + } + ++ _handleSelectChoice() {} ++ ++ _handleAnswerQuery() {} ++ + _handleBeginVerification() {} + + _handleSelectMechanism() { +diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js +index 0e5c525de..f257b55fc 100644 +--- a/js/gdm/authServicesLegacy.js ++++ b/js/gdm/authServicesLegacy.js +@@ -77,6 +77,14 @@ export class AuthServicesLegacy extends AuthServices { + this._fingerprintReadyTimeoutId = 0; + } + ++ _handleSelectChoice(serviceName, key) { ++ if (serviceName !== this._selectedMechanism?.serviceName) ++ return; ++ ++ this._userVerifierChoiceList.call_select_choice( ++ serviceName, key, this._cancellable).catch(logErrorUnlessCancelled); ++ } ++ + _handleAnswerQuery(serviceName, answer) { + if (serviceName !== this._selectedMechanism?.serviceName) + return; +@@ -246,11 +254,7 @@ export class AuthServicesLegacy extends AuthServices { + if (serviceName !== this._selectedMechanism?.serviceName) + return; + +- this.emit('ask-question', { +- serviceName, +- question, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), +- }); ++ this.emit('ask-question', {serviceName, question}); + } + + _handleOnSecretInfoQuery(serviceName, secretQuestion) { +@@ -262,7 +266,7 @@ export class AuthServicesLegacy extends AuthServices { + token = this._credentialManagers[serviceName].token; + + if (token) { +- this._handleAnswerQuery(serviceName, token); ++ this.answerQuery(serviceName, token); + return; + } + +@@ -270,7 +274,6 @@ export class AuthServicesLegacy extends AuthServices { + serviceName, + question: secretQuestion, + secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), + }); + } + +@@ -346,17 +349,7 @@ export class AuthServicesLegacy extends AuthServices { + for (const [key, value] of Object.entries(list.deepUnpack())) + choiceList[key] = {title: value}; + +- this.emit('show-choice-list', { +- serviceName, +- promptMessage, +- choiceList, +- choiceHandler: key => { +- if (serviceName !== this._selectedMechanism?.serviceName) +- return; +- this._userVerifierChoiceList.call_select_choice( +- serviceName, key, this._cancellable).catch(logErrorUnlessCancelled); +- }, +- }); ++ this.emit('show-choice-list', {serviceName, promptMessage, choiceList}); + } + + _handleGetCredentialManagerServices() { +diff --git a/js/gdm/authServicesSSSDSwitchable.js b/js/gdm/authServicesSSSDSwitchable.js +index 0271d98f2..3a81b99c2 100644 +--- a/js/gdm/authServicesSSSDSwitchable.js ++++ b/js/gdm/authServicesSSSDSwitchable.js +@@ -74,6 +74,23 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + } + } + ++ _handleSelectChoice(serviceName, key) { ++ if (serviceName !== this._selectedMechanism?.serviceName) ++ return; ++ ++ if (this._selectedMechanism.role === Role.SMARTCARD) { ++ const certificates = this._selectedMechanism.certificates; ++ const cert = certificates.find(c => c.keyId === key); ++ this._selectedSmartcard = cert; ++ this._promptStatus = PromptStatus.PIN_PROMPT; ++ this.emit('ask-question', { ++ serviceName, ++ question: cert.pinPrompt, ++ secret: true, ++ }); ++ } ++ } ++ + _handleAnswerQuery(serviceName, answer) { + if (serviceName !== this._selectedMechanism?.serviceName) + return; +@@ -349,7 +366,6 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + serviceName, + question: secretQuestion, + secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), + }); + } + } +@@ -437,12 +453,7 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + const {serviceName, prompt} = this._selectedMechanism; + + this._promptStatus = PromptStatus.PASSWORD_PROMPT; +- this.emit('ask-question', { +- serviceName, +- question: prompt, +- secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), +- }); ++ this.emit('ask-question', {serviceName, question: prompt, secret: true}); + } + + _startSmartcardLogin() { +@@ -455,7 +466,6 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + serviceName, + question: certificates[0].pinPrompt, + secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), + }); + return; + } +@@ -469,27 +479,7 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + : _('Select Identity'); + + this._promptStatus = PromptStatus.CERT_LIST_PROMPT; +- this.emit('show-choice-list', { +- serviceName, +- promptMessage, +- choiceList, +- choiceHandler: key => { +- if (serviceName !== this._selectedMechanism?.serviceName) +- return; +- +- if (this._selectedMechanism.role === Role.SMARTCARD) { +- const cert = this._selectedMechanism.certificates.find(c => c.keyId === key); +- this._selectedSmartcard = cert; +- this._promptStatus = PromptStatus.PIN_PROMPT; +- this.emit('ask-question', { +- serviceName, +- question: cert.pinPrompt, +- secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), +- }); +- } +- }, +- }); ++ this.emit('show-choice-list', {serviceName, promptMessage, choiceList}); + } + + _parseCertInstruction(certInstruction) { +@@ -524,12 +514,7 @@ export class AuthServicesSSSDSwitchable extends AuthServices { + } + + this._promptStatus = PromptStatus.PIN_PROMPT; +- this.emit('ask-question', { +- serviceName, +- question: pinPrompt, +- secret: true, +- answerHandler: answer => this._handleAnswerQuery(serviceName, answer), +- }); ++ this.emit('ask-question', {serviceName, question: pinPrompt, secret: true}); + + if (pinAttempts <= 3 && pinAttempts > 0) { + const message = _('You have %d attempts left. If the passkey gets locked, you may not able to access your account.').format(pinAttempts); +diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js +index 6c63a313d..116c4ae1d 100644 +--- a/js/gdm/userVerifier.js ++++ b/js/gdm/userVerifier.js +@@ -180,6 +180,18 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._settings = null; + } + ++ selectChoice(serviceName, key) { ++ this._authServices.forEach(s => s.selectChoice(serviceName, key)); ++ } ++ ++ async answerQuery(serviceName, answer) { ++ // Wait for pending messages to be displayed before answering to ++ // ensure no messages get lost ++ await this._handlePendingMessages().catch(logErrorUnlessCancelled); ++ ++ this._authServices.forEach(s => s.answerQuery(serviceName, answer)); ++ } ++ + addCredentialManager(serviceName, credentialManager) { + this._authServices.forEach(s => s.addCredentialManager(serviceName, credentialManager)); + } +@@ -464,14 +476,14 @@ export class ShellUserVerifier extends Signals.EventEmitter { + + async _waitPendingMessages({task}) { + try { +- await this.handlePendingMessages(); ++ await this._handlePendingMessages(); + task.return_boolean(true); + } catch (e) { + task.return_error(e); + } + } + +- handlePendingMessages() { ++ _handlePendingMessages() { + if (!this.hasPendingMessages) + return Promise.resolve(); + +-- +2.55.0 + + +From 3aae4d78f1432281589ff688d799c582bf80156b Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 12:40:53 +0200 +Subject: [PATCH 09/12] gdm: Restore positional signal signatures on + ShellUserVerifier + +Signals on ShellUserVerifier ('ask-question', 'show-message', +'show-choice-list', 'verification-failed', 'reset') were changed to +pass a single object argument instead of the original positional +arguments, breaking extensions that connect to them with the old +handler signatures (e.g. (verifier, serviceName, question, secret)). + +Restore the original positional argument order. Where the object +carried genuinely new information (like the show-message wiggle +resolver), append it as a trailing positional argument, which old +handlers simply ignore. +--- + js/gdm/authPrompt.js | 12 ++++++++---- + js/gdm/userVerifier.js | 20 +++++++++++--------- + 2 files changed, 19 insertions(+), 13 deletions(-) + +diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js +index bbf6c4e4e..97129ca00 100644 +--- a/js/gdm/authPrompt.js ++++ b/js/gdm/authPrompt.js +@@ -98,13 +98,17 @@ export const AuthPrompt = GObject.registerClass({ + this._userVerifier = this._createUserVerifier(this._gdmClient, {reauthenticationOnly}); + + this._userVerifier.connectObject( +- 'ask-question', (_, args) => this._onAskQuestion(args), +- 'show-message', (_, args) => this._onShowMessage(args), +- 'show-choice-list', (_, args) => this._onShowChoiceList(args), ++ 'ask-question', (_, serviceName, question, secret) => ++ this._onAskQuestion({serviceName, question, secret}), ++ 'show-message', (_, serviceName, message, type, shouldWiggle) => ++ this._onShowMessage({message, type, shouldWiggle}), ++ 'show-choice-list', (_, serviceName, promptMessage, choiceList) => ++ this._onShowChoiceList({serviceName, promptMessage, choiceList}), + 'show-button', (_, args) => this._onShowButton(args), + 'mechanisms-changed', (_, args) => this.emit('mechanisms-changed', args), + 'web-login', (_, args) => this._onWebLogin(args), +- 'verification-failed', (_, args) => this._onVerificationFailed(args), ++ 'verification-failed', (_, serviceName, canRetry) => ++ this._onVerificationFailed({serviceName, canRetry}), + 'verification-complete', () => this._onVerificationComplete(), + 'reset', (_, args) => this._onReset(args), + this); +diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js +index 116c4ae1d..e5d3a1835 100644 +--- a/js/gdm/userVerifier.js ++++ b/js/gdm/userVerifier.js +@@ -242,11 +242,11 @@ export class ShellUserVerifier extends Signals.EventEmitter { + const message = this.currentMessage; + + delete this._currentMessageExtraInterval; +- this.emit('show-message', { +- message: message.text, +- type: message.type, +- shouldWiggle: message.wiggle, +- }); ++ this.emit('show-message', ++ message.serviceName, ++ message.text, ++ message.type, ++ message.wiggle); + + this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, + message.interval + (this._currentMessageExtraInterval | 0), () => { +@@ -299,7 +299,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._messageQueueTimeoutId = 0; + } + +- this.emit('show-message', {type: MessageType.NONE}); ++ this.emit('show-message', null, null, MessageType.NONE); + } + + _reportInitError(initError) { +@@ -404,7 +404,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { + _connectAuthServices() { + this._authServices.forEach(authServices => { + authServices.connectObject( +- 'ask-question', (_, args) => this.emit('ask-question', args), ++ 'ask-question', (_, args) => ++ this.emit('ask-question', args.serviceName, args.question, args.secret ?? false), + 'queue-message', (_, args) => this._queueMessage(args), + 'queue-priority-message', (_, args) => this._queuePriorityMessage(args), + 'wait-pending-messages', (_, args) => this._waitPendingMessages(args), +@@ -412,7 +413,8 @@ export class ShellUserVerifier extends Signals.EventEmitter { + 'verification-failed', (_, args) => this._verificationFailed(args), + 'verification-complete', () => this.emit('verification-complete'), + 'reset', (_, args) => this.emit('reset', args), +- 'show-choice-list', (_, args) => this.emit('show-choice-list', args), ++ 'show-choice-list', (_, args) => ++ this.emit('show-choice-list', args.serviceName, args.promptMessage, args.choiceList), + 'show-button', (_, args) => this.emit('show-button', args), + 'mechanisms-changed', () => this._onMechanismsChanged(), + 'web-login', (_, args) => this.emit('web-login', args), +@@ -422,7 +424,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + + _verificationFailed({serviceName, canRetry}) { + this._filterServiceMessages({serviceName, messageType: MessageType.ERROR}); +- this.emit('verification-failed', {serviceName, canRetry}); ++ this.emit('verification-failed', serviceName, canRetry); + } + + get selectedMechanism() { +-- +2.55.0 + + +From 9c61a84b465df3bd0c83bbc6e3be5db811b5d04e Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 12:42:29 +0200 +Subject: [PATCH 10/12] gdm: Add backward-compatible property and method shims + +Several ShellUserVerifier properties and methods were dropped when +the class gained support for multiple concurrently-active AuthServices +(reauthenticating, smartcardDetected, serviceIsForeground(), +foregroundServiceDeterminesUsername(), serviceIsDefault(), +serviceIsFingerprint(), finishMessageQueue()), and AuthPrompt's +addCharacter() was renamed to startPreemptiveInput(). + +Restore reauthenticating as a real, tracked property, and add the +rest back as deprecated shims (documented with why they can no longer +be meaningfully implemented) so extensions calling them don't crash +with a TypeError. +--- + js/gdm/authPrompt.js | 8 ++++++ + js/gdm/userVerifier.js | 61 ++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 69 insertions(+) + +diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js +index 97129ca00..d062cdc4b 100644 +--- a/js/gdm/authPrompt.js ++++ b/js/gdm/authPrompt.js +@@ -923,6 +923,14 @@ export const AuthPrompt = GObject.registerClass({ + this._entry.clutter_text.insert_unichar(unichar); + } + ++ /** ++ * @deprecated Renamed to startPreemptiveInput(), kept for backward ++ * compatibility. ++ */ ++ addCharacter(unichar) { ++ this.startPreemptiveInput(unichar); ++ } ++ + _clearPreemptiveState() { + this._preemptiveInput = false; + this._preemptiveAnswer = null; +diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js +index e5d3a1835..2e863cb8b 100644 +--- a/js/gdm/userVerifier.js ++++ b/js/gdm/userVerifier.js +@@ -65,6 +65,9 @@ export class ShellUserVerifier extends Signals.EventEmitter { + this._messageQueue = []; + this._messageQueueTimeoutId = 0; + ++ // Kept for backward compatibility, see begin()/_getUserVerifierProxies(). ++ this.reauthenticating = false; ++ + this._settings = new Gio.Settings({schema_id: LOGIN_SCREEN_SCHEMA}); + this._settings.connect('changed', () => this._onSettingsChanged()); + this._updateAuthServices(); +@@ -82,9 +85,21 @@ export class ShellUserVerifier extends Signals.EventEmitter { + return this._messageQueue ? this._messageQueue[0] : null; + } + ++ /** ++ * @deprecated Kept for backward compatibility, always returns false. ++ * Smartcard detection is now internal to AuthServicesLegacy and no ++ * longer surfaced as a top-level property; the 'smartcard-status-changed' ++ * signal has also been removed. Use the 'mechanisms-changed' signal and ++ * check a mechanism's role instead. ++ */ ++ get smartcardDetected() { ++ return false; ++ } ++ + async begin(userName, hold) { + this._cancellable?.cancel(); + this._cancellable = new Gio.Cancellable(); ++ this.reauthenticating = false; + + try { + const proxies = await this._getUserVerifierProxies(userName, this._cancellable); +@@ -114,6 +129,51 @@ export class ShellUserVerifier extends Signals.EventEmitter { + return this._authServices.some(s => s.needsUsername()); + } + ++ /** ++ * @deprecated Kept for backward compatibility. Replaced by needsUsername(), ++ * of which this is the logical inverse: the "foreground service" concept ++ * no longer exists now that multiple AuthServices can be active at once, ++ * each exposing its own selectable mechanisms. ++ */ ++ foregroundServiceDeterminesUsername() { ++ return !this.needsUsername(); ++ } ++ ++ /** ++ * @deprecated Kept for backward compatibility, always returns false. ++ * There is no single "foreground service" anymore: each AuthServices ++ * instance tracks its own selected mechanism (see selectedMechanism). ++ */ ++ serviceIsForeground(_serviceName) { ++ return false; ++ } ++ ++ /** ++ * @deprecated Kept for backward compatibility, always returns false. ++ * Service roles are now assigned dynamically across AuthServices ++ * instances (see _redistributeRoles()) rather than through a single ++ * fixed default service. ++ */ ++ serviceIsDefault(_serviceName) { ++ return false; ++ } ++ ++ /** ++ * @deprecated Kept for backward compatibility, always returns false. ++ * Fingerprint handling is now internal to AuthServicesLegacy; use the ++ * 'mechanisms-changed' signal and check a mechanism's role instead. ++ */ ++ serviceIsFingerprint(_serviceName) { ++ return false; ++ } ++ ++ /** ++ * @deprecated Renamed to the private _finishMessageQueue(). ++ */ ++ finishMessageQueue() { ++ this._finishMessageQueue(); ++ } ++ + setDriverService(serviceName) { + if (this._driverService === serviceName) + return; +@@ -322,6 +382,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + try { + proxies.userVerifier = await this._client.open_reauthentication_channel( + userName, cancellable); ++ this.reauthenticating = true; + } catch (e) { + if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + throw e; +-- +2.55.0 + + +From 173fd8c7d0ace6b253df40d7db1260d0b202b17e Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 13:08:48 +0200 +Subject: [PATCH 11/12] authPrompt: updateSensitivity() signature + +updateSensitivity() started requiring a {sensitive} options object +instead of accepting a plain boolean. Restore its call signature. + +This also fixes _onUserStoppedTypePreemptiveAnswer(), which was +already calling updateSensitivity(false) with a bare boolean and +silently getting undefined out of the {sensitive} destructuring. +--- + js/gdm/authPrompt.js | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js +index d062cdc4b..8d4de6bde 100644 +--- a/js/gdm/authPrompt.js ++++ b/js/gdm/authPrompt.js +@@ -783,7 +783,11 @@ export const AuthPrompt = GObject.registerClass({ + wiggle(this._message, wiggleParameters); + } + +- updateSensitivity({sensitive}) { ++ updateSensitivity(params) { ++ // Kept for backward compatibility: this used to take a plain ++ // boolean instead of a {sensitive} options object. ++ const {sensitive} = typeof params === 'boolean' ? {sensitive: params} : params; ++ + if (sensitive && this._preemptiveAnswer) + return; + +-- +2.55.0 + + +From f3ee5bfd61b258f90fcfda784bac7e99194a89a5 Mon Sep 17 00:00:00 2001 +From: Joan Torres Lopez +Date: Wed, 12 Aug 2026 17:08:36 +0200 +Subject: [PATCH 12/12] gdm/userVerifier: needsUsername should use every + +When every authServices needUsername then return true, otherwise return +false. +--- + js/gdm/userVerifier.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/js/gdm/userVerifier.js b/js/gdm/userVerifier.js +index 2e863cb8b..e0a85c693 100644 +--- a/js/gdm/userVerifier.js ++++ b/js/gdm/userVerifier.js +@@ -126,7 +126,7 @@ export class ShellUserVerifier extends Signals.EventEmitter { + } + + needsUsername() { +- return this._authServices.some(s => s.needsUsername()); ++ return this._authServices.every(s => s.needsUsername()); + } + + /** +-- +2.55.0 + diff --git a/pre-changes-for-passwordless-gdm-backport.patch b/pre-changes-for-passwordless-gdm-backport.patch deleted file mode 100644 index 6171c45..0000000 --- a/pre-changes-for-passwordless-gdm-backport.patch +++ /dev/null @@ -1,217 +0,0 @@ - -From 1c91eaa7fb93536a1e3e2695d856721d403171f6 Mon Sep 17 00:00:00 2001 -From: Joan Torres Lopez -Date: Tue, 5 May 2026 17:26:27 +0200 -Subject: [PATCH 1/3] animationUtils: Skip no-op wiggle to avoid cancelling - pending transitions - -When wiggle() is called with duration 0, the async easeAsync calls -yield between microtasks, leaving pending operations that remove -transitions on the same property. This becomes a problem when two -setMessage() calls happen in the same call stack (e.g. via -_queuePriorityMessage): the first fires a no-op wiggle(dur:0) and -the second starts the real wiggle(dur:65). When microtasks drain, -the first wiggle's pending easeAsync calls overwrite the second -wiggle's active transition, effectively cancelling the real animation. - -Return early when duration is 0, since the animation is a no-op anyway. - -Fixes: fdadbb7a5a2 ("animationUtils: Use easeAsync() for wiggle") -Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/work_items/9207 -Part-of: ---- - js/misc/animationUtils.js | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/js/misc/animationUtils.js b/js/misc/animationUtils.js -index cf6889609..9d065cf78 100644 ---- a/js/misc/animationUtils.js -+++ b/js/misc/animationUtils.js -@@ -84,7 +84,7 @@ export function ensureActorVisibleInScrollView(scrollView, actor) { - * @param {number} params.wiggleCount - the number of times to wiggle the actor - */ - export function wiggle(actor, params) { -- if (!St.Settings.get().enable_animations) -+ if (!St.Settings.get().enable_animations || params?.duration === 0) - return; - - params = Params.parse(params, { --- -2.55.0 - - -From b5a37cbdd89eeed44966455ba22b0f10a3f25091 Mon Sep 17 00:00:00 2001 -From: Joan Torres Lopez -Date: Tue, 5 May 2026 21:32:06 +0200 -Subject: [PATCH 2/3] authPrompt: Call wiggle directly in _onShowMessage - -Part-of: ---- - js/gdm/authPrompt.js | 13 +++++-------- - 1 file changed, 5 insertions(+), 8 deletions(-) - -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index 3b4a2f798..f05856416 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -394,21 +394,20 @@ export const AuthPrompt = GObject.registerClass({ - } - - _onShowMessage(_userVerifier, serviceName, message, type) { -- let wiggleParameters = {duration: 0}; -+ this.setMessage(message, type); -+ this.emit('prompted'); - - if (type === GdmUtil.MessageType.ERROR && - this._userVerifier.serviceIsFingerprint(serviceName)) { - // TODO: Use Await for wiggle to be over before unfreezing the user verifier queue -- wiggleParameters = { -+ const wiggleParameters = { - duration: 65, - wiggleCount: 3, - }; - this._userVerifier.increaseCurrentMessageTimeout( - wiggleParameters.duration * (wiggleParameters.wiggleCount + 2)); -+ wiggle(this._message, wiggleParameters); - } -- -- this.setMessage(message, type, wiggleParameters); -- this.emit('prompted'); - } - - _onVerificationFailed(userVerifier, serviceName, canRetry) { -@@ -587,7 +586,7 @@ export const AuthPrompt = GObject.registerClass({ - }); - } - -- setMessage(message, type, wiggleParameters = {duration: 0}) { -+ setMessage(message, type) { - if (type === GdmUtil.MessageType.ERROR) - this._message.add_style_class_name('login-dialog-message-warning'); - else -@@ -607,8 +606,6 @@ export const AuthPrompt = GObject.registerClass({ - } else { - this._message.opacity = 0; - } -- -- wiggle(this._message, wiggleParameters); - } - - updateSensitivity(sensitive) { --- -2.55.0 - - -From 1e3f937a6ccfc8ea79c80d78df121102cffbdeff Mon Sep 17 00:00:00 2001 -From: Joan Torres Lopez -Date: Tue, 5 May 2026 17:28:18 +0200 -Subject: [PATCH 3/3] authPrompt: Await wiggle via show-message promise - resolver - -Pass promise resolver through the show-message signal so the -message queue waits for the wiggle animation to finish before scheduling -the next message timeout. This replaces the previous approach of manually -increasing the timeout duration to account for the wiggle. - -Part-of: ---- - js/gdm/authPrompt.js | 21 +++++++++------------ - js/gdm/util.js | 27 +++++++++++++++++---------- - 2 files changed, 26 insertions(+), 22 deletions(-) - -diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js -index f05856416..b1e8202bd 100644 ---- a/js/gdm/authPrompt.js -+++ b/js/gdm/authPrompt.js -@@ -393,21 +393,18 @@ export const AuthPrompt = GObject.registerClass({ - this.reset(); - } - -- _onShowMessage(_userVerifier, serviceName, message, type) { -+ _onShowMessage(_userVerifier, serviceName, message, type, showMessageResolver) { - this.setMessage(message, type); - this.emit('prompted'); - -- if (type === GdmUtil.MessageType.ERROR && -- this._userVerifier.serviceIsFingerprint(serviceName)) { -- // TODO: Use Await for wiggle to be over before unfreezing the user verifier queue -- const wiggleParameters = { -- duration: 65, -- wiggleCount: 3, -- }; -- this._userVerifier.increaseCurrentMessageTimeout( -- wiggleParameters.duration * (wiggleParameters.wiggleCount + 2)); -- wiggle(this._message, wiggleParameters); -- } -+ const shouldWiggle = type === GdmUtil.MessageType.ERROR && -+ this._userVerifier.serviceIsFingerprint(serviceName); -+ -+ const wigglePromise = shouldWiggle -+ ? wiggle(this._message, {duration: 65, wiggleCount: 3}) -+ : Promise.resolve(); -+ -+ showMessageResolver?.(wigglePromise); - } - - _onVerificationFailed(userVerifier, serviceName, canRetry) { -diff --git a/js/gdm/util.js b/js/gdm/util.js -index 4b0f763f0..e529f84fa 100644 ---- a/js/gdm/util.js -+++ b/js/gdm/util.js -@@ -262,11 +262,6 @@ export class ShellUserVerifier extends Signals.EventEmitter { - this.emit('no-more-messages'); - } - -- increaseCurrentMessageTimeout(interval) { -- if (!this._messageQueueTimeoutId && interval > 0) -- this._currentMessageExtraInterval = interval; -- } -- - _serviceHasPendingMessages(serviceName) { - return this._messageQueue.some(m => m.serviceName === serviceName); - } -@@ -279,17 +274,23 @@ export class ShellUserVerifier extends Signals.EventEmitter { - this._queuePriorityMessage(serviceName, null, messageType); - } - -- _queueMessageTimeout() { -- if (this._messageQueueTimeoutId !== 0) -+ async _queueMessageTimeout() { -+ if (this._messageQueueTimeoutId !== 0 || this._showMessageResolver) - return; - - const message = this.currentMessage; -+ const {promise, resolve} = Promise.withResolvers(); -+ this._showMessageResolver = resolve; - -- delete this._currentMessageExtraInterval; -- this.emit('show-message', message.serviceName, message.text, message.type); -+ this.emit('show-message', message.serviceName, message.text, message.type, this._showMessageResolver); -+ -+ await promise.catch(logError); -+ if (!this._showMessageResolver) -+ return; -+ this._showMessageResolver = null; - - this._messageQueueTimeoutId = GLib.timeout_add(GLib.PRIORITY_DEFAULT, -- message.interval + (this._currentMessageExtraInterval | 0), () => { -+ message.interval, () => { - this._messageQueueTimeoutId = 0; - - if (this._messageQueue.length > 1) { -@@ -332,6 +333,12 @@ export class ShellUserVerifier extends Signals.EventEmitter { - GLib.source_remove(this._messageQueueTimeoutId); - this._messageQueueTimeoutId = 0; - } -+ -+ if (this._showMessageResolver) { -+ this._showMessageResolver(); -+ this._showMessageResolver = null; -+ } -+ - this.emit('show-message', null, null, MessageType.NONE); - } - --- -2.55.0 -