From 183d2cce2a34a0d6fca990c2264bae60cdfc5de4 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 25 Mar 2026 18:58:29 +0100 Subject: [PATCH 01/30] gdm: Update styles from login-lock to login-dialog login-lock is used in newer versions, but in this version login-dialog is used. --- data/theme/gnome-shell-sass/_widgets.scss | 1 + .../widgets/_login-dialog.scss | 307 +++++++++++++++++- .../gnome-shell-sass/widgets/_qr-code.scss | 4 +- 3 files changed, 296 insertions(+), 16 deletions(-) diff --git a/data/theme/gnome-shell-sass/_widgets.scss b/data/theme/gnome-shell-sass/_widgets.scss index a8d0aa9f4d..1651d9ca3b 100644 --- a/data/theme/gnome-shell-sass/_widgets.scss +++ b/data/theme/gnome-shell-sass/_widgets.scss @@ -46,6 +46,7 @@ @import 'widgets/tiled-previews'; @import 'widgets/keyboard'; @import 'widgets/looking-glass'; +@import 'widgets/qr-code'; // Lock / login screens @import 'widgets/login-dialog'; @import 'widgets/screen-shield'; diff --git a/data/theme/gnome-shell-sass/widgets/_login-dialog.scss b/data/theme/gnome-shell-sass/widgets/_login-dialog.scss index 307a751628..f3aeed4bf3 100644 --- a/data/theme/gnome-shell-sass/widgets/_login-dialog.scss +++ b/data/theme/gnome-shell-sass/widgets/_login-dialog.scss @@ -1,5 +1,7 @@ /* Login Dialog */ +$_gdm_fg: $osd_fg_color; + .login-dialog-banner-view { padding-top: 24px; max-width: 23em; @@ -70,8 +72,10 @@ } } + .next-button, .cancel-button, .switch-user-button, + .login-dialog-auth-menu-button, .login-dialog-session-list-button { padding: 0; border-radius: 99px; @@ -83,10 +87,40 @@ StIcon { icon-size: $base_icon_size; } } + .next-button { + background-color: transparent !important; + } + + .switch-user-button { + min-width: 8.5em; + min-height: 2.5em; + @include fontsize($base_font_size - 1); + font-weight: bold; + } + .caps-lock-warning-label, .login-dialog-message-warning { color: $osd_fg_color; } + + .login-dialog-prompt-layout { + &.web-login-active { + width: 23em * 1.5; + } + } + + .login-dialog-prompt-entry-area { + margin: 0.5em $base_margin * 5; + } + + .login-dialog-prompt-entry { + border-radius: $base_border_radius * 1.5; + padding-right: 2.5em; // Make room for button-well inside entry + } + + .login-dialog-default-button-well { + margin-right: 0.4em; + } } .login-dialog-bottom-button-group { @@ -118,30 +152,185 @@ padding-top: 1em; } -.login-dialog-auth-list-view { -st-vfade-offset: 1em; } +.login-dialog-auth-menu-button-popup { + padding: $base_padding * 3; + margin-right: $base_padding * 2; + + .login-dialog-auth-menu-item-section { + padding-top: $base_padding; + + &:first-child { + padding-top: 0; + } + + &-label { + @include fontsize($base_font_size - 1); + font-weight: bold; + color: $_gdm_fg; + } + } + + .login-dialog-auth-menu-item-icon { + color: $_gdm_fg; + icon-size: $base_icon_size; + margin-right: $base_margin * 2; + } + + .login-dialog-auth-menu-item-box { + spacing: $base_padding * .5; + + &-name { + color: $_gdm_fg; + @include fontsize($base_font_size); + font-weight: bold; + } + + &-description { + color: $_gdm_fg; + @include fontsize($base_font_size - 1); + } + } +} + +.login-dialog-auth-menu-button-indicator { + background-color: transparent !important; + border-width: 0; + margin-bottom: 32px; + margin-left: 32px; + + .login-dialog-auth-menu-button-indicator-icons { + spacing: $base_padding * 3; + + .login-dialog-auth-menu-button-indicator-icon { + icon-size: 2em; + } + } + + .login-dialog-auth-menu-button-indicator-description { + @include fontsize($base_font_size); + margin-left: $base_padding * 2; + min-width: 20em; + } +} + +.login-dialog-button-box { + height: 4em; +} + +.login-dialog-auth-list-view { + -st-vfade-offset: 1em; + max-height: 13em; +} + .login-dialog-auth-list { - spacing: 6px; - margin-left: 2em; + spacing: $base_padding * 1.5; + width: 23em; + margin-left: $base_margin * 5; } -.login-dialog-auth-list-title { - margin-left: 2em; +.login-dialog { + .login-dialog-auth-list-title, + .login-dialog-auth-list-item { + border-radius: $base_border_radius * 1.5; + color: darken($_gdm_fg, 30%); + &:focus, &:selected { background-color: $selected_bg_color; color: $selected_fg_color; } + } + + .login-dialog-auth-list-title { + background-color: transparentize($_gdm_fg, .97) !important; + color: $_gdm_fg !important; + padding: $base_padding; + margin: 0.5em $base_margin * 5; + } + + .login-dialog-auth-list-item { + min-height: 3em; + padding: $base_padding * 1.5; + margin-bottom: $base_margin; + background-color: transparentize($_gdm_fg, .94); + } } -.login-dialog-auth-list-item { - border-radius: $base_border_radius + 4px; - padding: 6px; - color: darken($osd_fg_color,30%); - &:focus, &:selected { background-color: $selected_bg_color; color: $selected_fg_color; } +.unlock-dialog { + .login-dialog-auth-list-item { + border: none; + color: $osd_fg_color; + background-color: transparentize($osd_fg_color, 0.94); + &:hover, &:focus, &:selected { background-color: transparentize($osd_fg_color, 0.84); } + &:active { background-color: transparentize($osd_fg_color, 0.78); } + border-radius: $base_border_radius * 1.5; + min-height: 3em; + padding: $base_padding * 1.5; + margin-bottom: $base_margin; + } + + .login-dialog-auth-list-title { + background-color: transparent !important; + border: none; + color: $osd_fg_color !important; + padding: $base_padding; + } } -.login-dialog-auth-list-label { +.login-dialog-auth-list-title-label { @include fontsize($base_font_size + 2); font-weight: bold; - padding-left: 15px; + padding: $base_padding; + text-align: center; +} - &:ltr { padding-left: 14px; text-align: left; } - &:rtl { padding-right: 14px; text-align: right; } +.login-dialog-auth-list-item-title, +.login-dialog-auth-list-item-subtitle { + @include fontsize($base_font_size); + text-align: center; + padding: $base_padding * 0.3 0; +} + +.login-dialog-auth-list-item-title { + color: $_gdm_fg; + font-weight: bold; +} + +.login-dialog-auth-list-item-subtitle { + color: darken($_gdm_fg, 20%); + font-weight: 500; +} + +.login-dialog-item-icon { + width: 1.3em; + height: 1.3em; + color: $_gdm_fg; + padding: $base_padding * 0.7 $base_padding; + border-radius: $base_border_radius; + + &:hover { + background-color: $system_bg_color; + } + + &-popup { + &.popup-menu { + min-width: 0; + } + + &-box { + padding: $base_padding 0; + } + + &-box &-labels { + spacing: $base_padding * 0.5; + font-weight: bold; + text-align: center; + + & > :first-child { + color: darken($fg_color, 30%); + font-weight: 500; + } + + & > :last-child { + color: $fg_color; + } + } + } } .login-dialog-user-list-view { -st-vfade-offset: 1em; } @@ -207,3 +396,93 @@ @include fontsize($base_font_size + 1); padding-top: 1em; } + +.web-login-spinner { + background-color: rgba(0, 0, 0, 0.5); + border: 5px rgba(0, 0, 0, 0.0); + border-radius: 50px; +} + +.web-login-title-label { + @include fontsize($base_font_size); + color: darken($_gdm_fg,30%); + text-align: center; +} + +.web-login-url-label { + @include fontsize($base_font_size); + font-family: monospace; + color: $_gdm_fg; + text-align: center; + + &.web-login-url-label-long { + @include fontsize($base_font_size - 2); + } +} + +.web-login-code-title-label { + @include fontsize($base_font_size); + color: $_gdm_fg; + text-align: center; +} + +.web-login-code-label { + @include fontsize($base_font_size); + color: $_gdm_fg; + font-weight: bold; + text-align: center; +} + +.web-login-prompt { + padding-top: $base_padding; + padding-bottom: $base_padding; + padding-left: $base_padding * 4.5; + padding-right: $base_padding * 4.5; + spacing: 1.75em; +} + +.web-login-button-label { + @include fontsize($base_font_size + 2); + color: $_gdm_fg; + min-width: 12em; + text-align: center; + font-weight: bold; + padding-bottom: 0.1em; +} + +.login-dialog, +.unlock-dialog { + .web-login-intro-button, + .web-login-prompt-button { + border-radius: $base_border_radius * 4 !important; + padding: $base_padding * 1.5 $base_padding * 3; + background-color: transparentize($_gdm_fg, .94); + } + + .web-login-intro-button { + width: 10em; + } + + .web-login-prompt-button { + width: 7em; + margin: $base_margin * 6 $base_margin * 2; + } +} + +.login-dialog { + .web-login-intro-button, + .web-login-prompt-button { + &:hover, &:focus { + background-color: $selected_bg_color; + } + } +} + +.unlock-dialog { + .web-login-intro-button, + .web-login-prompt-button { + &:hover, &:focus { + background-color: transparentize($osd_fg_color, .84); + } + } +} diff --git a/data/theme/gnome-shell-sass/widgets/_qr-code.scss b/data/theme/gnome-shell-sass/widgets/_qr-code.scss index da04425bd6..0d733453f2 100644 --- a/data/theme/gnome-shell-sass/widgets/_qr-code.scss +++ b/data/theme/gnome-shell-sass/widgets/_qr-code.scss @@ -7,8 +7,8 @@ background-color: $qrcode_bg_color; border-color: $qrcode_bg_color; } @else { - background-color: $system_fg_color; - border-color: $system_fg_color; + background-color: $osd_fg_color; + border-color: $osd_fg_color; color: $system_bg_color; } } -- 2.51.0 From a6a9baab3e92e3adb9172227051e83c4d145e1df Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 14:52:58 +0100 Subject: [PATCH 02/30] gdm: Fix importing using the old gjs style --- js/gdm/authMenuButton.js | 13 +++++-------- js/gdm/authServices.js | 18 +++++++----------- js/gdm/authServicesLegacy.js | 18 ++++++++---------- js/gdm/authServicesSSSDSwitchable.js | 10 ++++------ js/gdm/webLogin.js | 14 +++++++------- js/misc/fingerprintManager.js | 10 ++++------ js/misc/passkeyDeviceManager.js | 3 +-- js/ui/qrCode.js | 10 +++------- 8 files changed, 39 insertions(+), 57 deletions(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index 9b7cebf6d8..f7f458dec8 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -1,4 +1,5 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +/* exported AuthMenuButton, AuthMenuButtonIndicator */ /* * Copyright 2024 Red Hat, Inc * @@ -43,15 +44,11 @@ * deactivates any other active item in the same section. */ -import Atk from 'gi://Atk'; -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Shell from 'gi://Shell'; -import St from 'gi://St'; +const { Atk, Clutter, GObject, Shell, St } = imports.gi; -import * as BoxPointer from '../ui/boxpointer.js'; -import * as Main from '../ui/main.js'; -import * as PopupMenu from '../ui/popupMenu.js'; +const BoxPointer = imports.ui.boxpointer; +const Main = imports.ui.main; +const PopupMenu = imports.ui.popupMenu; const VISIBILITY_ANIMATION_TIME = 200; diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index 0a94f493a2..0cafd2831c 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -1,16 +1,12 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- -import * as FingerprintManager from '../misc/fingerprintManager.js'; -import * as Params from '../misc/params.js'; -import {registerDestroyableType} from '../misc/signalTracker.js'; -import * as PasskeyDeviceManager from '../misc/passkeyDeviceManager.js'; -import * as SmartcardManager from '../misc/smartcardManager.js'; -import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; -import * as Util from './util.js'; -import Gdm from 'gi://Gdm'; -import GLib from 'gi://GLib'; -import Gio from 'gi://Gio'; -import GObject from 'gi://GObject'; +const { Gdm, Gio, GLib, GObject } = imports.gi; + +const FingerprintManager = imports.misc.fingerprintManager; +const Params = imports.misc.params; +const PasskeyDeviceManager = imports.misc.passkeyDeviceManager; +const SmartcardManager = imports.misc.smartcardManager; +const Util = imports.gdm.util; Gio._promisify(Gdm.Client.prototype, 'open_reauthentication_channel'); Gio._promisify(Gdm.Client.prototype, 'get_user_verifier'); diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js index c1ff1242dc..dd134db4b9 100644 --- a/js/gdm/authServicesLegacy.js +++ b/js/gdm/authServicesLegacy.js @@ -1,13 +1,11 @@ -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; - -import * as Constants from './constants.js'; -import {FingerprintReaderType} from '../misc/fingerprintManager.js'; -import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; -import * as OVirt from './oVirt.js'; -import * as Util from './util.js'; -import * as Vmware from './vmware.js'; -import {AuthServices} from './authServices.js'; +const { GLib, GObject } = imports.gi; + +const {AuthServices} = imports.gdm.authServices; +const Constants = imports.gdm.constants; +const {FingerprintReaderType} = imports.misc.fingerprintManager; +const OVirt = imports.gdm.oVirt; +const Util = imports.gdm.util; +const Vmware = imports.gdm.vmware; const FINGERPRINT_ERROR_TIMEOUT_WAIT = 15; const FINGERPRINT_READY_TIMEOUT_MS = 500; diff --git a/js/gdm/authServicesSSSDSwitchable.js b/js/gdm/authServicesSSSDSwitchable.js index de03dec1d7..4f74a2040d 100644 --- a/js/gdm/authServicesSSSDSwitchable.js +++ b/js/gdm/authServicesSSSDSwitchable.js @@ -1,10 +1,8 @@ -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; +const { GLib, GObject } = imports.gi; -import * as Constants from './constants.js'; -import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; -import * as Util from './util.js'; -import {AuthServices} from './authServices.js'; +const {AuthServices} = imports.gdm.authServices; +const Constants = imports.gdm.constants; +const Util = imports.gdm.util; const MechanismsStatus = { WAITING: 0, diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index 8f2a0d8767..ef4f28b592 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -3,13 +3,13 @@ // A widget showing a URL for web login /* exported WebLoginPrompt */ -import Clutter from 'gi://Clutter'; -import GObject from 'gi://GObject'; -import Pango from 'gi://Pango'; -import St from 'gi://St'; -import {Spinner} from '../ui/animation.js'; -import * as Params from '../misc/params.js'; -import {QrCode} from '../ui/qrCode.js'; +const { Clutter, Gio, GnomeQR, GObject, Pango, St } = imports.gi; + +const Params = imports.misc.params; +const { Spinner } = imports.ui.animation; +const { QrCode } = imports.ui.qrCode; + +Gio._promisify(GnomeQR, 'generate_qr_code_async'); const QR_CODE_SIZE = 150; const WEB_LOGIN_SPINNER_SIZE = 35; diff --git a/js/misc/fingerprintManager.js b/js/misc/fingerprintManager.js index 6ef2d68d3a..cdeb3579d1 100644 --- a/js/misc/fingerprintManager.js +++ b/js/misc/fingerprintManager.js @@ -1,13 +1,11 @@ -import Gio from 'gi://Gio'; -import GLib from 'gi://GLib'; -import GObject from 'gi://GObject'; +const { Gio, GLib, GObject } = imports.gi; -import {loadInterfaceXML} from './fileUtils.js'; +const FileUtils = imports.misc.fileUtils; const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml( - loadInterfaceXML('net.reactivated.Fprint.Manager')); + FileUtils.loadInterfaceXML('net.reactivated.Fprint.Manager')); const FprintDeviceInfo = Gio.DBusInterfaceInfo.new_for_xml( - loadInterfaceXML('net.reactivated.Fprint.Device')); + FileUtils.loadInterfaceXML('net.reactivated.Fprint.Device')); export const FingerprintReaderType = { NONE: 0, diff --git a/js/misc/passkeyDeviceManager.js b/js/misc/passkeyDeviceManager.js index 20799975aa..2aa81d2ce6 100644 --- a/js/misc/passkeyDeviceManager.js +++ b/js/misc/passkeyDeviceManager.js @@ -1,5 +1,4 @@ -import GObject from 'gi://GObject'; -import GUdev from 'gi://GUdev'; +const { GObject, GUdev } = imports.gi; let _passkeyDeviceManager = null; diff --git a/js/ui/qrCode.js b/js/ui/qrCode.js index caf0999f34..d1fac46847 100644 --- a/js/ui/qrCode.js +++ b/js/ui/qrCode.js @@ -1,10 +1,6 @@ -import Clutter from 'gi://Clutter'; -import Cogl from 'gi://Cogl'; -import GObject from 'gi://GObject'; -import Gio from 'gi://Gio'; -import GnomeQR from 'gi://GnomeQR'; -import St from 'gi://St'; -import {logErrorUnlessCancelled} from '../misc/errorUtils.js'; +/* exported QrCode */ + +const { Clutter, Cogl, Gio, GnomeQR, GObject, St } = imports.gi; Gio._promisify(GnomeQR, 'generate_qr_code_async'); -- 2.51.0 From 12ea582a78b26f37c9c7bdd12af35718cbbae961 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 14:58:42 +0100 Subject: [PATCH 03/30] gdm: Fix using the old gjs style for classes and functions --- js/gdm/authList.js | 45 +++++++++------------- js/gdm/authMenuButton.js | 57 +++++++++++----------------- js/gdm/authServices.js | 20 ++++------ js/gdm/authServicesLegacy.js | 15 ++++---- js/gdm/authServicesSSSDSwitchable.js | 15 ++++---- js/gdm/constants.js | 22 ++++++----- js/gdm/util.js | 9 +++-- js/gdm/webLogin.js | 20 +++++----- js/misc/fingerprintManager.js | 30 +++++++-------- js/misc/passkeyDeviceManager.js | 23 +++++------ js/ui/qrCode.js | 40 +++++++++---------- 11 files changed, 131 insertions(+), 165 deletions(-) diff --git a/js/gdm/authList.js b/js/gdm/authList.js index 3f1b2817f9..6eb34f6d97 100644 --- a/js/gdm/authList.js +++ b/js/gdm/authList.js @@ -57,13 +57,10 @@ const ItemIconPopup = class extends PopupMenu.PopupMenu { } }; +const ItemIcon = GObject.registerClass( class ItemIcon extends St.Button { - static { - GObject.registerClass(this); - } - - constructor(iconName, iconTitle, iconSubtitle) { - super({ + _init(iconName, iconTitle, iconSubtitle) { + super._init({ style_class: 'login-dialog-item-icon', iconName, }); @@ -71,21 +68,17 @@ class ItemIcon extends St.Button { this._popup = new ItemIconPopup(this, iconTitle, iconSubtitle); Main.uiGroup.add_child(this._popup.actor); } -} +}); -class AuthListItem extends St.Button { - static [GObject.signals] = { +const AuthListItem = GObject.registerClass({ + Signals: { 'activate': {}, - }; - - static { - GObject.registerClass(this); - } - - constructor(key, content) { + }, +}, class AuthListItem extends St.Button { + _init(key, content) { const {title, subtitle, iconName, iconTitle, iconSubtitle} = content; - super({ + super._init({ style_class: 'login-dialog-auth-list-item', button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, can_focus: true, @@ -168,20 +161,16 @@ class AuthListItem extends St.Button { this.remove_style_pseudo_class('selected'); } } -} +}); -export class AuthList extends St.BoxLayout { - static [GObject.signals] = { +var AuthList = GObject.registerClass({ + Signals: { 'activate': {param_types: [GObject.TYPE_STRING]}, 'item-added': {param_types: [AuthListItem.$gtype]}, - }; - - static { - GObject.registerClass(this); } - - constructor() { - super({ +}, class AuthList extends St.BoxLayout { + _init() { + super._init({ orientation: Clutter.Orientation.VERTICAL, style_class: 'login-dialog-auth-list-layout', y_align: Clutter.ActorAlign.CENTER, @@ -278,4 +267,4 @@ export class AuthList extends St.BoxLayout { this._box.destroy_all_children(); this._items.clear(); } -} +}); diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index f7f458dec8..e58c331b45 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -71,13 +71,10 @@ class AuthMenuItemSection extends PopupMenu.PopupMenuSection { } } +const AuthMenuItem = GObject.registerClass( class AuthMenuItem extends PopupMenu.PopupBaseMenuItem { - static { - GObject.registerClass(this); - } - - constructor(item, params = {}) { - super(params); + _init(item, params = {}) { + super._init(params); if (item.description && item.iconName) { const icon = new St.Icon({ @@ -117,42 +114,37 @@ class AuthMenuItem extends PopupMenu.PopupBaseMenuItem { this.setOrnament(PopupMenu.Ornament.HIDDEN); } -} +}); -export class AuthMenuButton extends St.Button { - static [GObject.properties] = { +var AuthMenuButton = GObject.registerClass({ + Properties: { 'title': GObject.ParamSpec.string( - 'title', null, null, + 'title', 'title', 'title', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, ''), 'icon-name': GObject.ParamSpec.string( - 'icon-name', null, null, + 'icon-name', 'icon-name', 'icon-name', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, ''), 'read-only': GObject.ParamSpec.boolean( - 'read-only', null, null, + 'read-only', 'read-only', 'read-only', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, false), 'section-order': GObject.ParamSpec.jsobject( - 'section-order', null, null, + 'section-order', 'section-order', 'section-order', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY), 'animate-visibility': GObject.ParamSpec.boolean( - 'animate-visibility', null, null, + 'animate-visibility', 'animate-visibility', 'animate-visibility', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT_ONLY, false), - }; - - static [GObject.signals] = { + }, + Signals: { 'active-item-changed': {param_types: [GObject.TYPE_STRING]}, - }; - - static { - GObject.registerClass(this); - } - - constructor(params) { + }, +}, class AuthMenuButton extends St.Button { + _init(params) { params.sectionOrder ??= []; - super({ + super._init({ ...params, style_class: 'login-dialog-button login-dialog-auth-menu-button', reactive: true, @@ -452,16 +444,13 @@ export class AuthMenuButton extends St.Button { closeMenu() { this._menu.close(); } -} +}); -export class AuthMenuButtonIndicator extends AuthMenuButton { - static { - GObject.registerClass(this); - } - - constructor(params = {}) { +var AuthMenuButtonIndicator = GObject.registerClass( +class AuthMenuButtonIndicator extends AuthMenuButton { + _init(params = {}) { params.readOnly ??= true; - super(params); + super._init(params); this.add_style_class_name('login-dialog-auth-menu-button-indicator'); } @@ -526,4 +515,4 @@ export class AuthMenuButtonIndicator extends AuthMenuButton { // Override to force visibility even when there's only one item _updateVisibility() { } -} +}); diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index 0cafd2831c..ce4f0729b3 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -1,4 +1,5 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +/* exported AuthServices */ const { Gdm, Gio, GLib, GObject } = imports.gi; @@ -16,8 +17,8 @@ Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_answer_query'); Gio._promisify(Gdm.UserVerifierChoiceListProxy.prototype, 'call_select_choice'); Gio._promisify(Gdm.UserVerifierCustomJSONProxy.prototype, 'call_reply'); -export class AuthServices extends GObject.Object { - static [GObject.signals] = { +var AuthServices = GObject.registerClass({ + Signals: { 'destroy': {}, 'queue-message': { param_types: [GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_UINT], @@ -51,13 +52,8 @@ export class AuthServices extends GObject.Object { GObject.TYPE_STRING, GObject.TYPE_STRING, GObject.TYPE_JSOBJECT, ], }, - }; - - static { - GObject.registerClass(this); - registerDestroyableType(this); - } - + }, +}, class AuthServices extends GObject.Object { static SupportedRoles = []; static RoleToService = {}; @@ -65,8 +61,8 @@ export class AuthServices extends GObject.Object { return roles.some(r => this.SupportedRoles.includes(r)); } - constructor(params) { - super(); + _init(params) { + super._init(); params = Params.parse(params, { client: null, enabledRoles: [], @@ -502,4 +498,4 @@ export class AuthServices extends GObject.Object { throw new GObject.NotImplementedError( `_handleCanStartService in ${this.constructor.name}`); } -} +}); diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js index dd134db4b9..8922546474 100644 --- a/js/gdm/authServicesLegacy.js +++ b/js/gdm/authServicesLegacy.js @@ -1,3 +1,5 @@ +/* exported AuthServicesLegacy */ + const { GLib, GObject } = imports.gi; const {AuthServices} = imports.gdm.authServices; @@ -28,7 +30,8 @@ const Mechanisms = [ }, ]; -export class AuthServicesLegacy extends AuthServices { +var AuthServicesLegacy = GObject.registerClass({ +}, class AuthServicesLegacy extends AuthServices { static SupportedRoles = [ Constants.PASSWORD_ROLE_NAME, Constants.SMARTCARD_ROLE_NAME, @@ -41,12 +44,8 @@ export class AuthServicesLegacy extends AuthServices { [Constants.FINGERPRINT_ROLE_NAME]: Constants.FINGERPRINT_SERVICE_NAME, }; - static { - GObject.registerClass(this); - } - - constructor(params) { - super(params); + _init(params) { + super._init(params); this._updateEnabledMechanisms(); @@ -378,4 +377,4 @@ export class AuthServicesLegacy extends AuthServices { }; this.emit('reset', {softReset: true}); } -} +}); diff --git a/js/gdm/authServicesSSSDSwitchable.js b/js/gdm/authServicesSSSDSwitchable.js index 4f74a2040d..4b4761d105 100644 --- a/js/gdm/authServicesSSSDSwitchable.js +++ b/js/gdm/authServicesSSSDSwitchable.js @@ -1,3 +1,5 @@ +/* exported AuthServicesSwitchable */ + const { GLib, GObject } = imports.gi; const {AuthServices} = imports.gdm.authServices; @@ -10,7 +12,8 @@ const MechanismsStatus = { FOUND: 2, }; -export class AuthServicesSSSDSwitchable extends AuthServices { +var AuthServicesSSSDSwitchable = GObject.registerClass({ +}, class AuthServicesSSSDSwitchable extends AuthServices { static SupportedRoles = [ Constants.PASSWORD_ROLE_NAME, Constants.SMARTCARD_ROLE_NAME, @@ -25,12 +28,8 @@ export class AuthServicesSSSDSwitchable extends AuthServices { [Constants.WEB_LOGIN_ROLE_NAME]: Constants.SWITCHABLE_AUTH_SERVICE_NAME, }; - static { - GObject.registerClass(this); - } - - constructor(params) { - super(params); + _init(params) { + super._init(params); this._mechanismsStatus = MechanismsStatus.WAITING; } @@ -440,4 +439,4 @@ export class AuthServicesSSSDSwitchable extends AuthServices { GLib.source_remove(this._webLoginTimeoutId); this._webLoginTimeoutId = 0; } -} +}); diff --git a/js/gdm/constants.js b/js/gdm/constants.js index 7c48599e64..cfbbe32426 100644 --- a/js/gdm/constants.js +++ b/js/gdm/constants.js @@ -1,12 +1,16 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +/* exported PASSWORD_ROLE_NAME, SMARTCARD_ROLE_NAME, FINGERPRINT_ROLE_NAME, + PASSKEY_ROLE_NAME, WEB_LOGIN_ROLE_NAME, PASSWORD_SERVICE_NAME, + SMARTCARD_SERVICE_NAME, FINGERPRINT_SERVICE_NAME, + SWITCHABLE_AUTH_SERVICE_NAME */ -export const PASSWORD_ROLE_NAME = 'password'; -export const SMARTCARD_ROLE_NAME = 'smartcard'; -export const FINGERPRINT_ROLE_NAME = 'fingerprint'; -export const PASSKEY_ROLE_NAME = 'passkey'; -export const WEB_LOGIN_ROLE_NAME = 'eidp'; +var PASSWORD_ROLE_NAME = 'password'; +var SMARTCARD_ROLE_NAME = 'smartcard'; +var FINGERPRINT_ROLE_NAME = 'fingerprint'; +var PASSKEY_ROLE_NAME = 'passkey'; +var WEB_LOGIN_ROLE_NAME = 'eidp'; -export const PASSWORD_SERVICE_NAME = 'gdm-password'; -export const SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; -export const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; -export const SWITCHABLE_AUTH_SERVICE_NAME = 'gdm-switchable-auth'; +var PASSWORD_SERVICE_NAME = 'gdm-password'; +var SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; +var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; +var SWITCHABLE_AUTH_SERVICE_NAME = 'gdm-switchable-auth'; diff --git a/js/gdm/util.js b/js/gdm/util.js index 743fce11b7..f1709edea3 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -1,6 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- /* exported BANNER_MESSAGE_KEY, BANNER_MESSAGE_TEXT_KEY, LOGO_KEY, - DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor */ + DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor, + InitError, isSelectable, getIconName */ const { Clutter, Gio, GLib } = imports.gi; const Signals = imports.signals; @@ -125,7 +126,7 @@ function cloneAndFadeOutActor(actor) { * a service via beginVerification fails. It wraps the underlying error * and provides context about which service failed. */ -export class InitError extends Error { +var InitError = class extends Error { constructor(error, message, serviceName) { super(message, {cause: error}); this.serviceName = serviceName; @@ -136,7 +137,7 @@ export class InitError extends Error { * @param {object} mechanism * @returns {boolean} */ -export function isSelectable(mechanism) { +function isSelectable(mechanism) { switch (mechanism.role) { case Constants.PASSWORD_ROLE_NAME: case Constants.SMARTCARD_ROLE_NAME: @@ -154,7 +155,7 @@ export function isSelectable(mechanism) { * @param {object} mechanism * @returns {string} */ -export function getNonSelectableIconName(mechanism) { +function getNonSelectableIconName(mechanism) { // This is only used for non selectable mechanisms. // Currently only fingerprint is non selectable if (isSelectable(mechanism)) diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index ef4f28b592..9c858f7269 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -1,7 +1,7 @@ // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- // // A widget showing a URL for web login -/* exported WebLoginPrompt */ +/* exported QrCode, WebLoginPrompt, WebLoginDialog, WebLoginIntro */ const { Clutter, Gio, GnomeQR, GObject, Pango, St } = imports.gi; @@ -15,9 +15,9 @@ const QR_CODE_SIZE = 150; const WEB_LOGIN_SPINNER_SIZE = 35; const URL_LABEL_LONG_THRESHOLD = 45; -export const WebLoginPrompt = GObject.registerClass( +var WebLoginPrompt = GObject.registerClass( class WebLoginPrompt extends St.BoxLayout { - constructor(params) { + _init(params) { const {qrSize: qrCodeSize, message, url, code} = Params.parse(params, { qrSize: QR_CODE_SIZE, message: null, @@ -25,7 +25,7 @@ class WebLoginPrompt extends St.BoxLayout { code: null, }); - super({ + super._init({ styleClass: 'web-login-prompt', vertical: true, y_align: Clutter.ActorAlign.CENTER, @@ -124,13 +124,13 @@ class WebLoginPrompt extends St.BoxLayout { } }); -export const WebLoginDialog = GObject.registerClass({ +var WebLoginDialog = GObject.registerClass({ Signals: { 'cancel': {}, 'loading': {}, }, }, class WebLoginDialog extends St.Widget { - constructor(params) { + _init(params) { const {message, url, code, buttons} = Params.parse(params, { message: null, url: null, @@ -138,7 +138,7 @@ export const WebLoginDialog = GObject.registerClass({ buttons: [], }); - super({ + super._init({ layout_manager: new Clutter.BinLayout(), x_expand: true, y_expand: true, @@ -279,9 +279,9 @@ export const WebLoginDialog = GObject.registerClass({ } }); -export var WebLoginIntro = GObject.registerClass( +var WebLoginIntro = GObject.registerClass( class WebLoginIntro extends St.Button { - constructor(params) { + _init(params) { const {message} = Params.parse(params, { message: null, }); @@ -291,7 +291,7 @@ class WebLoginIntro extends St.Button { style_class: 'web-login-button-label', }); - super({ + super._init({ style_class: 'web-login-intro-button', accessible_name: message, button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, diff --git a/js/misc/fingerprintManager.js b/js/misc/fingerprintManager.js index cdeb3579d1..151e787e0b 100644 --- a/js/misc/fingerprintManager.js +++ b/js/misc/fingerprintManager.js @@ -1,4 +1,5 @@ const { Gio, GLib, GObject } = imports.gi; +/* exported FingerprintReaderType, FingerprintManager */ const FileUtils = imports.misc.fileUtils; @@ -7,7 +8,7 @@ const FprintManagerInfo = Gio.DBusInterfaceInfo.new_for_xml( const FprintDeviceInfo = Gio.DBusInterfaceInfo.new_for_xml( FileUtils.loadInterfaceXML('net.reactivated.Fprint.Device')); -export const FingerprintReaderType = { +var FingerprintReaderType = { NONE: 0, PRESS: 1, SWIPE: 2, @@ -18,32 +19,27 @@ let _fingerprintManager = null; /** * @returns {FingerprintManager} */ -export function getFingerprintManager() { +function getFingerprintManager() { if (_fingerprintManager == null) _fingerprintManager = new FingerprintManager(); return _fingerprintManager; } -class FingerprintManager extends GObject.Object { - static [GObject.properties] = { +var FingerprintManager = GObject.registerClass({ + Properties: { 'reader-type': GObject.ParamSpec.uint( - 'reader-type', null, null, + 'reader-type', 'reader-type', 'reader-type', GObject.ParamFlags.READWRITE, FingerprintReaderType.NONE, FingerprintReaderType.SWIPE, FingerprintReaderType.NONE), - }; - - static [GObject.signals] = { + }, + Signals: { 'reader-type-changed': {}, - }; - - static { - GObject.registerClass(this); - } - - constructor() { - super(); + }, +}, class FingerprintManager extends GObject.Object { + _init() { + super._init(); this._fingerprintManagerProxy = new Gio.DBusProxy({ g_connection: Gio.DBus.system, @@ -133,4 +129,4 @@ class FingerprintManager extends GObject.Object { logError(e, 'Failed to interact with fprintd service'); } -} +}); diff --git a/js/misc/passkeyDeviceManager.js b/js/misc/passkeyDeviceManager.js index 2aa81d2ce6..747ee93fc8 100644 --- a/js/misc/passkeyDeviceManager.js +++ b/js/misc/passkeyDeviceManager.js @@ -1,30 +1,27 @@ const { GObject, GUdev } = imports.gi; +/* exported getPasskeyDeviceManager */ + let _passkeyDeviceManager = null; /** * @returns {PasskeyDeviceManager} */ -export function getPasskeyDeviceManager() { +function getPasskeyDeviceManager() { if (_passkeyDeviceManager == null) _passkeyDeviceManager = new PasskeyDeviceManager(); return _passkeyDeviceManager; } -class PasskeyDeviceManager extends GObject.Object { - static [GObject.signals] = { +var PasskeyDeviceManager = GObject.registerClass({ + Signals: { 'passkey-inserted': {param_types: [GObject.TYPE_JSOBJECT]}, 'passkey-removed': {param_types: [GObject.TYPE_JSOBJECT]}, - }; - - static { - GObject.registerClass(this); - } - - constructor() { - super(); - + }, +}, class PasskeyDeviceManager extends GObject.Object { + _init() { + super._init(); this._insertedPasskeys = new Map(); this._udevClient = new GUdev.Client({subsystems: ['hidraw']}); @@ -65,4 +62,4 @@ class PasskeyDeviceManager extends GObject.Object { this._insertedPasskeys.delete(sysfsPath); this.emit('passkey-removed', device); } -} +}); diff --git a/js/ui/qrCode.js b/js/ui/qrCode.js index d1fac46847..5920e45e5a 100644 --- a/js/ui/qrCode.js +++ b/js/ui/qrCode.js @@ -7,43 +7,39 @@ Gio._promisify(GnomeQR, 'generate_qr_code_async'); const QR_CODE_DEFAULT_SIZE = 150; const QR_CODE_TRANSPARENT_COLOR = new GnomeQR.Color({alpha: 0}); -export class QrCode extends St.Bin { - static [GObject.properties] = { +var QrCode = GObject.registerClass({ + Properties: { 'url': GObject.ParamSpec.string( - 'url', null, null, + 'url', 'url', 'url', GObject.ParamFlags.READWRITE, null), - }; - - static { - GObject.registerClass(this); - } - - constructor(params) { + }, +}, class QrCode extends St.Bin { + _init(params) { const qrSize = Math.max(params.width ?? 0, params.height ?? 0) || QR_CODE_DEFAULT_SIZE; - super({ - styleClass: 'qr-code', + super._init({ + style_class: 'qr-code', width: qrSize, height: qrSize, ...params, }); this.set_child(new Clutter.Actor({ - xExpand: true, - yExpand: true, - xAlign: Clutter.ActorAlign.FILL, - yAlign: Clutter.ActorAlign.FILL, - minificationFilter: Clutter.ScalingFilter.NEAREST, - magnificationFilter: Clutter.ScalingFilter.NEAREST, + x_expand: true, + y_expand: true, + x_align: Clutter.ActorAlign.FILL, + y_align: Clutter.ActorAlign.FILL, + minification_filter: Clutter.ScalingFilter.NEAREST, + magnification_filter: Clutter.ScalingFilter.NEAREST, })); this._fgColor = null; this.connect('notify::url', () => this._update().catch(logErrorUnlessCancelled)); - }; + } vfunc_allocate(box) { const width = box.get_width(); @@ -69,7 +65,7 @@ export class QrCode extends St.Bin { } async _update() { - const fgColor = QrCode.#getGnomeQRColor(this._fgColor); + const fgColor = QrCode._getGnomeQRColor(this._fgColor); this._cancellable?.cancel(); const cancellable = new Gio.Cancellable(); @@ -100,7 +96,7 @@ export class QrCode extends St.Bin { this.child.set_content(content); } - static #getGnomeQRColor(color) { + static _getGnomeQRColor(color) { if (!color) return null; @@ -111,4 +107,4 @@ export class QrCode extends St.Bin { alpha: color.alpha, }); } -}; +}); -- 2.51.0 From 8d635a7b5f8da824025ae9e206cd2cdf92bc83ff Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 15:01:19 +0100 Subject: [PATCH 04/30] gdm: Fix using logErrorUnless cancelled This function doesn't exist in this version. --- js/gdm/authServices.js | 3 ++- js/gdm/authServicesLegacy.js | 12 +++++++++--- js/gdm/authServicesSSSDSwitchable.js | 12 +++++++++--- js/gdm/util.js | 5 ++++- js/ui/qrCode.js | 13 ++++++++++--- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index ce4f0729b3..fea7ba0634 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -373,7 +373,8 @@ var AuthServices = GObject.registerClass({ await this._waitPendingMessages(); this.emit('reset', {softReset: !doneTrying}); } catch (e) { - logErrorUnlessCancelled(e); + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); } } diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js index 8922546474..0fd0e10d81 100644 --- a/js/gdm/authServicesLegacy.js +++ b/js/gdm/authServicesLegacy.js @@ -1,6 +1,6 @@ /* exported AuthServicesLegacy */ -const { GLib, GObject } = imports.gi; +const { Gio, GLib, GObject } = imports.gi; const {AuthServices} = imports.gdm.authServices; const Constants = imports.gdm.constants; @@ -61,7 +61,10 @@ var AuthServicesLegacy = GObject.registerClass({ return; this._userVerifierChoiceList.call_select_choice( - serviceName, key, this._cancellable).catch(logErrorUnlessCancelled); + serviceName, key, this._cancellable).catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); } _handleAnswerQuery(serviceName, answer) { @@ -72,7 +75,10 @@ var AuthServicesLegacy = GObject.registerClass({ this._smartcardInProgress = true; this._userVerifier.call_answer_query( - serviceName, answer, this._cancellable).catch(logErrorUnlessCancelled); + serviceName, answer, this._cancellable).catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); } _handleBeginVerification() { diff --git a/js/gdm/authServicesSSSDSwitchable.js b/js/gdm/authServicesSSSDSwitchable.js index 4b4761d105..601f4cd295 100644 --- a/js/gdm/authServicesSSSDSwitchable.js +++ b/js/gdm/authServicesSSSDSwitchable.js @@ -1,6 +1,6 @@ /* exported AuthServicesSwitchable */ -const { GLib, GObject } = imports.gi; +const { Gio, GLib, GObject } = imports.gi; const {AuthServices} = imports.gdm.authServices; const Constants = imports.gdm.constants; @@ -54,7 +54,10 @@ var AuthServicesSSSDSwitchable = GObject.registerClass({ this._resettingPassword) { this._userVerifier.call_answer_query(serviceName, answer, - this._cancellable).catch(logErrorUnlessCancelled); + this._cancellable).catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); return; } @@ -316,7 +319,10 @@ var AuthServicesSSSDSwitchable = GObject.registerClass({ const {serviceName} = this._selectedMechanism; this._userVerifierCustomJSON.call_reply( - serviceName, JSON.stringify(response), this._cancellable).catch(logErrorUnlessCancelled); + serviceName, JSON.stringify(response), this._cancellable).catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); } _eventExpected() { diff --git a/js/gdm/util.js b/js/gdm/util.js index f1709edea3..17892c75e8 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -282,7 +282,10 @@ var ShellUserVerifier = class { async answerQuery(serviceName, answer) { // Wait for pending messages to be displayed before answering to // ensure no messages get lost - await this._handlePendingMessages().catch(logErrorUnlessCancelled); + await this._handlePendingMessages().catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); this._authServicesSSSDSwitchable?.answerQuery(serviceName, answer); this._authServicesLegacy?.answerQuery(serviceName, answer); diff --git a/js/ui/qrCode.js b/js/ui/qrCode.js index 5920e45e5a..b53508c2dd 100644 --- a/js/ui/qrCode.js +++ b/js/ui/qrCode.js @@ -37,8 +37,12 @@ var QrCode = GObject.registerClass({ this._fgColor = null; - this.connect('notify::url', () => - this._update().catch(logErrorUnlessCancelled)); + this.connect('notify::url', () => { + this._update().catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); + }); } vfunc_allocate(box) { @@ -60,7 +64,10 @@ var QrCode = GObject.registerClass({ if (!this._fgColor?.equal(fgColor)) { this._fgColor = fgColor; - this._update().catch(logErrorUnlessCancelled); + this._update().catch(e => { + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + logError(e); + }); } } -- 2.51.0 From 147ad05d7d926478da5d35ea14bcec81bf0795ee Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 12:58:59 +0100 Subject: [PATCH 05/30] gdm: Change connectObject to connect connectObject is a helper that isn't available in this older version. --- js/gdm/authPrompt.js | 24 +++--- js/gdm/authServices.js | 138 +++++++++++++++++++++++++---------- js/gdm/authServicesLegacy.js | 26 ++++++- js/gdm/util.js | 61 +++++++++++----- js/gdm/webLogin.js | 11 ++- 5 files changed, 186 insertions(+), 74 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index 8c5c8a1fab..6996dac18b 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -81,16 +81,16 @@ var AuthPrompt = GObject.registerClass({ this._userVerifier = new GdmUtil.ShellUserVerifier(this._gdmClient, { reauthenticationOnly }); - this._userVerifier.connectObject( - 'ask-question', this._onAskQuestion.bind(this), - 'show-message', this._onShowMessage.bind(this), - 'show-choice-list', this._onShowChoiceList.bind(this), - 'mechanisms-changed', (_, ...args) => this.emit('mechanisms-changed', ...args), - 'web-login', this._onWebLogin.bind(this), - 'verification-failed', this._onVerificationFailed.bind(this), - 'verification-complete', this._onVerificationComplete.bind(this), - 'reset', this._onReset.bind(this), - this); + this._userVerifierSignalIds = [ + this._userVerifier.connect('ask-question', this._onAskQuestion.bind(this)), + this._userVerifier.connect('show-message', this._onShowMessage.bind(this)), + this._userVerifier.connect('show-choice-list', this._onShowChoiceList.bind(this)), + this._userVerifier.connect('mechanisms-changed', (_, ...args) => this.emit('mechanisms-changed', ...args)), + this._userVerifier.connect('web-login', this._onWebLogin.bind(this)), + this._userVerifier.connect('verification-failed', this._onVerificationFailed.bind(this)), + this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)), + this._userVerifier.connect('reset', this._onReset.bind(this)), + ]; this.connect('destroy', this._onDestroy.bind(this)); @@ -134,7 +134,9 @@ var AuthPrompt = GObject.registerClass({ this._preemptiveAnswerWatchId = 0; } - this._userVerifier.disconnectObject(this); + this._userVerifierSignalIds.forEach(id => + this._userVerifier.disconnect(id)); + this._userVerifierSignalIds = []; this._userVerifier.destroy(); this._userVerifier = null; this._entry = null; diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index fea7ba0634..88462cf17e 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -165,6 +165,8 @@ var AuthServices = GObject.registerClass({ destroy() { this.reset(); this.clear(); + this._disconnectManagers(); + this._handleDestroy(); this.emit('destroy'); } @@ -202,10 +204,35 @@ var AuthServices = GObject.registerClass({ } _disconnectUserVerifierSignals() { - this._userVerifier?.get_connection().disconnectObject(this); - this._userVerifier?.disconnectObject(this); - this._userVerifierChoiceList?.disconnectObject(this); - this._userVerifierCustomJSON?.disconnectObject(this); + this._userVerifierConnectionSignalIds?.forEach(id => + this._userVerifier?.get_connection().disconnect(id)); + this._userVerifierConnectionSignalIds = []; + + this._userVerifierSignalIds?.forEach(id => + this._userVerifier?.disconnect(id)); + this._userVerifierSignalIds = []; + + this._userVerifierChoiceListSignalIds?.forEach(id => + this._userVerifierChoiceList?.disconnect(id)); + this._userVerifierChoiceListSignalIds = []; + + this._userVerifierCustomJSONSignalIds?.forEach(id => + this._userVerifierCustomJSON?.disconnect(id)); + this._userVerifierCustomJSONSignalIds = []; + } + + _disconnectManagers() { + this._smartcardManagerSignalIds?.forEach(id => + this._smartcardManager?.disconnect(id)); + this._smartcardManagerSignalIds = []; + + this._passkeyDeviceManagerSignalIds?.forEach(id => + this._passkeyDeviceManager?.disconnect(id)); + this._passkeyDeviceManagerSignalIds = []; + + this._fingerprintManagerSignalIds?.forEach(id => + this._fingerprintManager?.disconnect(id)); + this._fingerprintManagerSignalIds = []; } _updateEnabledMechanisms() { @@ -218,18 +245,24 @@ var AuthServices = GObject.registerClass({ _connectSmartcardManager() { this._smartcardManager = SmartcardManager.getSmartcardManager(); - this._smartcardManager.connectObject( - 'smartcard-inserted', () => this._handleSmartcardChanged(), - 'smartcard-removed', () => this._handleSmartcardChanged(), - this); + this._smartcardManagerSignalIds = []; + let id = this._smartcardManager.connect('smartcard-inserted', + () => this._handleSmartcardChanged()); + this._smartcardManagerSignalIds.push(id); + id = this._smartcardManager.connect('smartcard-removed', + () => this._handleSmartcardChanged()); + this._smartcardManagerSignalIds.push(id); } _connectPasskeyDeviceManager() { this._passkeyDeviceManager = PasskeyDeviceManager.getPasskeyDeviceManager(); - this._passkeyDeviceManager.connectObject( - 'passkey-inserted', () => this._handlePasskeyChanged(), - 'passkey-removed', () => this._handlePasskeyChanged(), - this); + this._passkeyDeviceManagerSignalIds = []; + let id = this._passkeyDeviceManager.connect('passkey-inserted', + () => this._handlePasskeyChanged()); + this._passkeyDeviceManagerSignalIds.push(id); + id = this._passkeyDeviceManager.connect('passkey-removed', + () => this._handlePasskeyChanged()); + this._passkeyDeviceManagerSignalIds.push(id); } _connectFingerprintManager() { @@ -237,10 +270,11 @@ var AuthServices = GObject.registerClass({ if (!this._reauthOnly) return; - this._fingerprintManager = FingerprintManager.getFingerprintManager(); - this._fingerprintManager.connectObject( - 'reader-type-changed', () => this._handleFingerprintChanged(), - this); + this._fingerprintManager = new FingerprintManager.FingerprintManager(); + this._fingerprintManagerSignalIds = []; + let id = this._fingerprintManager.connect('reader-type-changed', + () => this._handleFingerprintChanged()); + this._fingerprintManagerSignalIds.push(id); } _waitPendingMessages() { @@ -276,29 +310,53 @@ var AuthServices = GObject.registerClass({ } _connectUserVerifierSignals() { - this._userVerifier.get_connection().connectObject( - 'closed', () => this._clearUserVerifier(), - this); - - this._userVerifier.connectObject( - 'info', (_, ...args) => this._onInfo(...args), - 'problem', (_, ...args) => this._onProblem(...args), - 'info-query', (_, ...args) => this._onInfoQuery(...args), - 'secret-info-query', (_, ...args) => this._onSecretInfoQuery(...args), - 'conversation-started', (_, ...args) => this._onConversationStarted(...args), - 'conversation-stopped', (_, ...args) => this._onConversationStopped(...args), - 'service-unavailable', (_, ...args) => this._onServiceUnavailable(...args), - 'reset', () => this.emit('reset', {}), - 'verification-complete', (_, ...args) => this._onVerificationComplete(...args), - this); - - this._userVerifierChoiceList?.connectObject( - 'choice-query', (_, ...args) => this._onChoiceListQuery(...args), - this); - - this._userVerifierCustomJSON?.connectObject( - 'request', (_, ...args) => this._onCustomJSONRequest(...args), - this); + this._userVerifierConnectionSignalIds = []; + let id = this._userVerifier.get_connection().connect('closed', + () => this._clearUserVerifier()); + this._userVerifierConnectionSignalIds.push(id); + + this._userVerifierSignalIds = []; + id = this._userVerifier.connect('info', + (_, ...args) => this._onInfo(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('problem', + (_, ...args) => this._onProblem(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('info-query', + (_, ...args) => this._onInfoQuery(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('secret-info-query', + (_, ...args) => this._onSecretInfoQuery(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('conversation-started', + (_, ...args) => this._onConversationStarted(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('conversation-stopped', + (_, ...args) => this._onConversationStopped(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('service-unavailable', + (_, ...args) => this._onServiceUnavailable(...args)); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('reset', + () => this.emit('reset', {})); + this._userVerifierSignalIds.push(id); + id = this._userVerifier.connect('verification-complete', + (_, ...args) => this._onVerificationComplete(...args)); + this._userVerifierSignalIds.push(id); + + this._userVerifierChoiceListSignalIds = []; + if (this._userVerifierChoiceList) { + id = this._userVerifierChoiceList.connect('choice-query', + (_, ...args) => this._onChoiceListQuery(...args)); + this._userVerifierChoiceListSignalIds.push(id); + } + + this._userVerifierCustomJSONSignalIds = []; + if (this._userVerifierCustomJSON) { + id = this._userVerifierCustomJSON.connect('request', + (_, ...args) => this._onCustomJSONRequest(...args)); + this._userVerifierCustomJSONSignalIds.push(id); + } } _onInfo(serviceName, info) { @@ -456,6 +514,8 @@ var AuthServices = GObject.registerClass({ _handleClear() {} + _handleDestroy() {} + _handleUpdateEnabledRoles() {} _handleUpdateEnabledMechanisms() { diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js index 0fd0e10d81..5955aeadff 100644 --- a/js/gdm/authServicesLegacy.js +++ b/js/gdm/authServicesLegacy.js @@ -50,6 +50,7 @@ var AuthServicesLegacy = GObject.registerClass({ this._updateEnabledMechanisms(); this._credentialManagers = {}; + this._credentialManagerSignalIds = {}; this.addCredentialManager(OVirt.SERVICE_NAME, OVirt.getOVirtCredentialsManager()); this.addCredentialManager(Vmware.SERVICE_NAME, Vmware.getVmwareCredentialsManager()); @@ -104,6 +105,20 @@ var AuthServicesLegacy = GObject.registerClass({ this._selectedMechanism = null; } + _handleDestroy() { + this._disconnectCredentialManagers(); + } + + _disconnectCredentialManagers() { + Object.keys(this._credentialManagerSignalIds).forEach(serviceName => { + const signalId = this._credentialManagerSignalIds[serviceName]; + const credentialManager = this._credentialManagers[serviceName]; + if (signalId) + credentialManager?.disconnect(signalId); + }); + this._credentialManagerSignalIds = {}; + } + _handleClear() { this._smartcardInProgress = false; this._clearFingerprintReadyTimeout(); @@ -359,9 +374,9 @@ var AuthServicesLegacy = GObject.registerClass({ if (credentialManager.token) this._onCredentialManagerAuthenticated(credentialManager); - credentialManager.connectObject( - 'user-authenticated', () => this._onCredentialManagerAuthenticated(credentialManager), - this); + const id = credentialManager.connect('user-authenticated', + () => this._onCredentialManagerAuthenticated(credentialManager)); + this._credentialManagerSignalIds[serviceName] = id; } removeCredentialManager(serviceName) { @@ -369,7 +384,10 @@ var AuthServicesLegacy = GObject.registerClass({ if (!credentialManager) return; - credentialManager.disconnectObject(this); + const signalId = this._credentialManagerSignalIds[serviceName]; + if (signalId) + credentialManager.disconnect(signalId); + delete this._credentialManagerSignalIds[serviceName]; delete this._credentialManagers[serviceName]; if (this._selectedMechanism?.serviceName === serviceName) diff --git a/js/gdm/util.js b/js/gdm/util.js index 17892c75e8..85de597d33 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -270,6 +270,8 @@ var ShellUserVerifier = class { this.cancel(); + this._clearAuthServices(); + this._settings.run_dispose(); this._settings = null; } @@ -498,31 +500,54 @@ var ShellUserVerifier = class { } _clearAuthServices() { + this._authServicesSSSDSwitchableSignalIds?.forEach(id => + this._authServicesSSSDSwitchable?.disconnect(id)); + this._authServicesSSSDSwitchableSignalIds = []; this._authServicesSSSDSwitchable?.destroy(); this._authServicesSSSDSwitchable = null; + + this._authServicesLegacySignalIds?.forEach(id => + this._authServicesLegacy?.disconnect(id)); + this._authServicesLegacySignalIds = []; this._authServicesLegacy?.destroy(); this._authServicesLegacy = null; } _connectAuthServices() { - [ - this._authServicesSSSDSwitchable, - this._authServicesLegacy, - ].forEach(authServices => { - authServices?.connectObject( - 'ask-question', (_, ...args) => this.emit('ask-question', ...args), - 'queue-message', (_, ...args) => this._queueMessage(...args), - 'queue-priority-message', (_, ...args) => this._queuePriorityMessage(...args), - 'wait-pending-messages', (_, ...args) => this._waitPendingMessages(...args), - 'filter-messages', (_, ...args) => this._filterServiceMessages(...args), - 'verification-failed', (_, ...args) => this._verificationFailed(...args), - 'verification-complete', (_, ...args) => this.emit('verification-complete', ...args), - 'reset', (_, ...args) => this.emit('reset', ...args), - 'show-choice-list', (_, ...args) => this.emit('show-choice-list', ...args), - 'mechanisms-changed', (_, ...args) => this._onMechanismsChanged(...args), - 'web-login', (_, ...args) => this.emit('web-login', ...args), - this); - }); + const connectSignals = authServices => { + if (!authServices) + return []; + + return [ + authServices.connect('ask-question', + (_, ...args) => this.emit('ask-question', ...args)), + authServices.connect('queue-message', + (_, ...args) => this._queueMessage(...args)), + authServices.connect('queue-priority-message', + (_, ...args) => this._queuePriorityMessage(...args)), + authServices.connect('wait-pending-messages', + (_, ...args) => this._waitPendingMessages(...args)), + authServices.connect('filter-messages', + (_, ...args) => this._filterServiceMessages(...args)), + authServices.connect('verification-failed', + (_, ...args) => this._verificationFailed(...args)), + authServices.connect('verification-complete', + (_, ...args) => this.emit('verification-complete', ...args)), + authServices.connect('reset', + (_, ...args) => this.emit('reset', ...args)), + authServices.connect('show-choice-list', + (_, ...args) => this.emit('show-choice-list', ...args)), + authServices.connect('mechanisms-changed', + (_, ...args) => this._onMechanismsChanged(...args)), + authServices.connect('web-login', + (_, ...args) => this.emit('web-login', ...args)), + ]; + }; + + this._authServicesSSSDSwitchableSignalIds = + connectSignals(this._authServicesSSSDSwitchable); + this._authServicesLegacySignalIds = + connectSignals(this._authServicesLegacy); } _verificationFailed(serviceName, canRetry) { diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index 9c858f7269..26da94b624 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -182,7 +182,14 @@ var WebLoginDialog = GObject.registerClass({ } _updateButtons(buttons) { + this._buttonBox.get_children().forEach(b => { + if (b._clickedSignalId) { + b.disconnect(b._clickedSignalId); + b._clickedSignalId = 0; + } + }); this._buttonBox.destroy_all_children(); + this._cancelButton = this._addButton({ label: _('Cancel'), action: () => this.emit('cancel'), @@ -202,11 +209,11 @@ var WebLoginDialog = GObject.registerClass({ }), }); - button.connectObject('clicked', () => { + button._clickedSignalId = button.connect('clicked', () => { if (b.needsLoading) this._startLoading(); b.action(); - }, this); + }); button.default = b.default; -- 2.51.0 From bcf392cbdac51d1bb1fb2e161c674bc4bd3286a6 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 15:12:16 +0100 Subject: [PATCH 06/30] gdm: Use promisify adding two params This is how it works in this old version --- js/gdm/authServices.js | 12 +++++------- js/gdm/util.js | 7 ++++++- js/gdm/webLogin.js | 2 +- js/ui/qrCode.js | 2 +- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index 88462cf17e..3cb1985817 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -9,13 +9,11 @@ const PasskeyDeviceManager = imports.misc.passkeyDeviceManager; const SmartcardManager = imports.misc.smartcardManager; const Util = imports.gdm.util; -Gio._promisify(Gdm.Client.prototype, 'open_reauthentication_channel'); -Gio._promisify(Gdm.Client.prototype, 'get_user_verifier'); -Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification_for_user'); -Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification'); -Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_answer_query'); -Gio._promisify(Gdm.UserVerifierChoiceListProxy.prototype, 'call_select_choice'); -Gio._promisify(Gdm.UserVerifierCustomJSONProxy.prototype, 'call_reply'); +Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification_for_user', 'call_begin_verification_for_user_finish'); +Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification', 'call_begin_verification_finish'); +Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_answer_query', 'call_answer_query_finish'); +Gio._promisify(Gdm.UserVerifierChoiceListProxy.prototype, 'call_select_choice', 'call_select_choice_finish'); +Gio._promisify(Gdm.UserVerifierCustomJSONProxy.prototype, 'call_reply', 'call_reply_finish'); var AuthServices = GObject.registerClass({ Signals: { diff --git a/js/gdm/util.js b/js/gdm/util.js index 85de597d33..4aeec5b02a 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -3,7 +3,7 @@ DISABLE_USER_LIST_KEY, fadeInActor, fadeOutActor, cloneAndFadeOutActor, InitError, isSelectable, getIconName */ -const { Clutter, Gio, GLib } = imports.gi; +const { Clutter, Gdm, Gio, GLib } = imports.gi; const Signals = imports.signals; const Batch = imports.gdm.batch; @@ -13,6 +13,11 @@ const Params = imports.misc.params; const { AuthServicesLegacy } = imports.gdm.authServicesLegacy; const { AuthServicesSSSDSwitchable } = imports.gdm.authServicesSSSDSwitchable; +Gio._promisify(Gdm.Client.prototype, 'open_reauthentication_channel', 'open_reauthentication_channel_finish'); +Gio._promisify(Gdm.Client.prototype, 'get_user_verifier', 'get_user_verifier_finish'); +Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification_for_user', 'call_begin_verification_for_user_finish'); +Gio._promisify(Gdm.UserVerifierProxy.prototype, 'call_begin_verification', 'call_begin_verification_finish'); + var FADE_ANIMATION_TIME = 160; var CLONE_FADE_ANIMATION_TIME = 250; diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index 26da94b624..f4972144fa 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -9,7 +9,7 @@ const Params = imports.misc.params; const { Spinner } = imports.ui.animation; const { QrCode } = imports.ui.qrCode; -Gio._promisify(GnomeQR, 'generate_qr_code_async'); +Gio._promisify(GnomeQR, 'generate_qr_code_async', 'generate_qr_code_finish'); const QR_CODE_SIZE = 150; const WEB_LOGIN_SPINNER_SIZE = 35; diff --git a/js/ui/qrCode.js b/js/ui/qrCode.js index b53508c2dd..547ad7d153 100644 --- a/js/ui/qrCode.js +++ b/js/ui/qrCode.js @@ -2,7 +2,7 @@ const { Clutter, Cogl, Gio, GnomeQR, GObject, St } = imports.gi; -Gio._promisify(GnomeQR, 'generate_qr_code_async'); +Gio._promisify(GnomeQR, 'generate_qr_code_async', 'generate_qr_code_finish'); const QR_CODE_DEFAULT_SIZE = 150; const QR_CODE_TRANSPARENT_COLOR = new GnomeQR.Color({alpha: 0}); -- 2.51.0 From 74a94cb0c34413d45ef2e1d599822c25c434e1b8 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 13:52:50 +0100 Subject: [PATCH 07/30] gdm: Use timeout_add_seconds instead of once _once type doesn't exist in this old glib version --- js/gdm/authServices.js | 7 +++++-- js/gdm/authServicesSSSDSwitchable.js | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index 3cb1985817..003b4836a6 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -277,8 +277,11 @@ var AuthServices = GObject.registerClass({ _waitPendingMessages() { const cancellable = this._cancellable; - const timeoutId = GLib.timeout_add_seconds_once(GLib.PRIORITY_DEFAULT, 10, - () => cancellable.cancel()); + const timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 10, + () => { + cancellable.cancel(); + return GLib.SOURCE_REMOVE; + }); const {promise, resolve, reject} = Promise.withResolvers(); const task = Gio.Task.new(this, cancellable, () => { diff --git a/js/gdm/authServicesSSSDSwitchable.js b/js/gdm/authServicesSSSDSwitchable.js index 601f4cd295..48c1c020fb 100644 --- a/js/gdm/authServicesSSSDSwitchable.js +++ b/js/gdm/authServicesSSSDSwitchable.js @@ -195,7 +195,7 @@ var AuthServicesSSSDSwitchable = GObject.registerClass({ if (!timeout) return; - this._webLoginTimeoutId = GLib.timeout_add_seconds_once(GLib.PRIORITY_DEFAULT, + this._webLoginTimeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, timeout, () => { if (this._selectedMechanism?.role !== Constants.WEB_LOGIN_ROLE_NAME) webLoginMechanism.needsRefresh = true; @@ -203,6 +203,7 @@ var AuthServicesSSSDSwitchable = GObject.registerClass({ this.emit('reset', {softReset: true}); this._webLoginTimeoutId = 0; + return GLib.SOURCE_REMOVE; }); } -- 2.51.0 From aff9353c2f80c15111f9b7f772b5fa45277251fd Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 13:56:56 +0100 Subject: [PATCH 08/30] gdm: fix Promise.withResolvers Use manual new Promise to extract them. --- js/gdm/authServices.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/js/gdm/authServices.js b/js/gdm/authServices.js index 003b4836a6..00d19004f3 100644 --- a/js/gdm/authServices.js +++ b/js/gdm/authServices.js @@ -283,7 +283,11 @@ var AuthServices = GObject.registerClass({ return GLib.SOURCE_REMOVE; }); - const {promise, resolve, reject} = Promise.withResolvers(); + let resolve, reject; + const promise = new Promise((_resolve, _reject) => { + resolve = _resolve; + reject = _reject; + }); const task = Gio.Task.new(this, cancellable, () => { try { const res = task.propagate_boolean(); -- 2.51.0 From fdad9ac3e5bb6699d835d23a50033244fefc6907 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 19:33:38 +0100 Subject: [PATCH 09/30] data/theme: Add new icons to theme gresource They were in a different icons gresource that doesn't exist in 40 vesion --- data/gnome-shell-theme.gresource.xml | 2 ++ data/icons/meson.build | 1 + 2 files changed, 3 insertions(+) diff --git a/data/gnome-shell-theme.gresource.xml b/data/gnome-shell-theme.gresource.xml index 7857f4407b..4f697f88df 100644 --- a/data/gnome-shell-theme.gresource.xml +++ b/data/gnome-shell-theme.gresource.xml @@ -4,6 +4,8 @@ calendar-today.svg carousel-arrow-next-24-symbolic.svg carousel-arrow-back-24-symbolic.svg + ../icons/scalable/status/fingerprint-auth-symbolic.svg + ../icons/scalable/status/vcard-symbolic.svg checkbox-focused.svg checkbox-off-focused.svg checkbox-off.svg diff --git a/data/icons/meson.build b/data/icons/meson.build index eff6e4b530..44e2b164a3 100644 --- a/data/icons/meson.build +++ b/data/icons/meson.build @@ -1 +1,2 @@ install_subdir('hicolor', install_dir: icondir) +install_subdir('scalable', install_dir: icondir) -- 2.51.0 From e0b648ce306e29ecb754711700d0b95aa4ed8769 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 15 Dec 2025 13:34:27 +0100 Subject: [PATCH 10/30] gdm/authmenuButton: Use None ornament NOT_DOT doesn't exist. --- js/gdm/authMenuButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index e58c331b45..9a02b0cb05 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -236,7 +236,7 @@ var AuthMenuButton = GObject.registerClass({ _updateOrnament() { for (const menuItem of this._items.values()) - menuItem.setOrnament(PopupMenu.Ornament.NO_DOT); + menuItem.setOrnament(PopupMenu.Ornament.NONE); for (const itemKey of this._activeItems) { const menuItem = this._getMenuItem(JSON.parse(itemKey)); -- 2.51.0 From 6a246865fb5a2da8724aafea34995d5aab81c263 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 20:33:15 +0100 Subject: [PATCH 11/30] gdm/authMenuButton: Add proper style classes to button --- js/gdm/authMenuButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index 9a02b0cb05..64dcf1a3f4 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -146,7 +146,7 @@ var AuthMenuButton = GObject.registerClass({ params.sectionOrder ??= []; super._init({ ...params, - style_class: 'login-dialog-button login-dialog-auth-menu-button', + style_class: 'modal-dialog-button button login-dialog-auth-menu-button', reactive: true, track_hover: true, can_focus: true, -- 2.51.0 From 11ad6201e3c032674d4e58f44d9fea9820fb4234 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 2 Jan 2026 14:48:42 +0100 Subject: [PATCH 12/30] gdm/authMenuButton: Add style to indicator description This is needed to set its color in the lockscreen. --- data/theme/gnome-shell-sass/widgets/_login-dialog.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data/theme/gnome-shell-sass/widgets/_login-dialog.scss b/data/theme/gnome-shell-sass/widgets/_login-dialog.scss index f3aeed4bf3..29c6803082 100644 --- a/data/theme/gnome-shell-sass/widgets/_login-dialog.scss +++ b/data/theme/gnome-shell-sass/widgets/_login-dialog.scss @@ -123,6 +123,10 @@ $_gdm_fg: $osd_fg_color; } } +.login-dialog-auth-menu-button-indicator-description { + color: $osd_fg_color; +} + .login-dialog-bottom-button-group { padding: 32px; spacing: 16px; -- 2.51.0 From d7c9b074f8cb0bf2295daa3a518776cae023a039 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 17:57:03 +0100 Subject: [PATCH 13/30] gdm/authMenuButton: Add no-op () instead of null --- js/gdm/authMenuButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index 64dcf1a3f4..a211ebe0d8 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -475,7 +475,7 @@ class AuthMenuButtonIndicator extends AuthMenuButton { this._descriptionLabel, 'visible', GObject.BindingFlags.SYNC_CREATE, (bind, source) => [true, !!source], - null); + () => {}); container.add_child(this._descriptionLabel); return container; -- 2.51.0 From 5fb0f23fda55d433a08db68920ed896cdf9e3d08 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 2 Apr 2026 19:38:34 +0200 Subject: [PATCH 14/30] gdm/authMenuButton: Ensure visible of description is properly binded to its text --- js/gdm/authMenuButton.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index a211ebe0d8..3dafd87630 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -510,6 +510,7 @@ class AuthMenuButtonIndicator extends AuthMenuButton { updateDescriptionLabel() { const [item] = this._items.size === 1 ? this.getItems() : []; this._descriptionLabel.text = item?.description ?? ''; + this._descriptionLabel.visible = !!this._descriptionLabel.text; } // Override to force visibility even when there's only one item -- 2.51.0 From e9abaf90b24df1f98108ab48c5d00ec87a6d5c9e Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 13:38:06 +0100 Subject: [PATCH 15/30] Fix foreach in wrong type Map.keys() returns an iterator which doesn't have .forEach() in older SpiderMonkey. Wrapped it with [...] to convert to an array first. --- js/gdm/authMenuButton.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index 3dafd87630..393dc5da4b 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -307,7 +307,7 @@ var AuthMenuButton = GObject.registerClass({ this._items.delete(itemKey); }); - this._sections.keys().forEach(sectionName => { + [...this._sections.keys()].forEach(sectionName => { const itemsInSection = this._findItems({sectionName}); if (itemsInSection.length === 0) { const section = this._sections.get(sectionName); -- 2.51.0 From 2e28cf05ef0033c42c6bb54839184701718bf48a Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 12:56:24 +0100 Subject: [PATCH 16/30] Change ??= by if statement This old js version doesn't support it. --- js/gdm/authMenuButton.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/gdm/authMenuButton.js b/js/gdm/authMenuButton.js index 393dc5da4b..c5e864c686 100644 --- a/js/gdm/authMenuButton.js +++ b/js/gdm/authMenuButton.js @@ -143,7 +143,8 @@ var AuthMenuButton = GObject.registerClass({ }, }, class AuthMenuButton extends St.Button { _init(params) { - params.sectionOrder ??= []; + if (params.sectionOrder === undefined || params.sectionOrder === null) + params.sectionOrder = []; super._init({ ...params, style_class: 'modal-dialog-button button login-dialog-auth-menu-button', @@ -449,7 +450,8 @@ var AuthMenuButton = GObject.registerClass({ var AuthMenuButtonIndicator = GObject.registerClass( class AuthMenuButtonIndicator extends AuthMenuButton { _init(params = {}) { - params.readOnly ??= true; + if (params.readOnly === undefined || params.readOnly === null) + params.readOnly = true; super._init(params); this.add_style_class_name('login-dialog-auth-menu-button-indicator'); -- 2.51.0 From f55cd19afd2028dda3af2bb1490c13ca06caf759 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 18:26:49 +0100 Subject: [PATCH 17/30] gdm/util: Don't return a promise in wait-pending-messages The callback of wait-pending-messages was returning a Promise. That was causing the error "Could not guess unspecified GValue type". Avoid it embracing the callback with {} so the return isn't passed. --- js/gdm/util.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/util.js b/js/gdm/util.js index 4aeec5b02a..629ba1b629 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -531,7 +531,7 @@ var ShellUserVerifier = class { authServices.connect('queue-priority-message', (_, ...args) => this._queuePriorityMessage(...args)), authServices.connect('wait-pending-messages', - (_, ...args) => this._waitPendingMessages(...args)), + (_, ...args) => {this._waitPendingMessages(...args);}), authServices.connect('filter-messages', (_, ...args) => this._filterServiceMessages(...args)), authServices.connect('verification-failed', -- 2.51.0 From 179858faf126b93d734452ebb522383b07bf0a1d Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 16:26:57 +0100 Subject: [PATCH 18/30] gdm/authPrompt: Fixes 1. Don't set directly icon_name in StButton 2. Guard setting text on entries on clear 3. Use Const instead of GdmUtil to get standard service_names 4. Inputwell was an extra container, in old version directly store in this. 5. On setChoiceList, don't hide _message. This keeps the same layout avoiding height increase of mainBox 6. On vfunc_key_press_event, handle event more explicitly instead of just calling event. --- js/gdm/authPrompt.js | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index 6996dac18b..7f683b2ba0 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -146,8 +146,17 @@ var AuthPrompt = GObject.registerClass({ if (keyPressEvent.keyval == Clutter.KEY_Escape) this.cancel(); - if (this._preemptiveInput && !this._pendingActivate) - return this._entry.clutter_text.event(keyPressEvent, false); + if (this._preemptiveInput && !this._pendingActivate) { + const unichar = keyPressEvent.unicode_value; + if (keyPressEvent.keyval === Clutter.KEY_Return && + this._entry.clutter_text.text) { + this._pendingActivate = true; + } else if (GLib.unichar_isprint(unichar)) { + this._entry.clutter_text.insert_text(unichar, + this._entry.clutter_text.cursor_position); + } + return Clutter.EVENT_STOP; + } return super.vfunc_key_press_event(keyPressEvent); } @@ -200,7 +209,7 @@ var AuthPrompt = GObject.registerClass({ }, }); }); - this._inputWell.add_child(this._authList); + this.add_child(this._authList); // Use an insensitive button for the auth list title // to get the same style as the auth list buttons @@ -291,7 +300,7 @@ var AuthPrompt = GObject.registerClass({ button_mask: St.ButtonMask.ONE | St.ButtonMask.THREE, reactive: true, can_focus: false, - icon_name: 'go-next-symbolic', + child: new St.Icon({icon_name: 'go-next-symbolic'}), }); this._nextButton.connect('clicked', () => this._activateNext()); this._nextButton.add_style_pseudo_class('default'); @@ -322,7 +331,7 @@ var AuthPrompt = GObject.registerClass({ } }); this._webLoginDialog.connect('loading', () => this.emit('loading', this._webLoginDialog.isLoading)); - this._inputWell.add_child(this._webLoginDialog); + this.add_child(this._webLoginDialog); } _updateShowPasswordIcon() { @@ -638,8 +647,10 @@ var AuthPrompt = GObject.registerClass({ }); if (!reuseEntryText) { - this._entry.text = ''; - this._inactiveEntry.text = ''; + if (this._entry) + this._entry.text = ''; + if (this._inactiveEntry) + this._inactiveEntry.text = ''; } this._entryArea.hide(); @@ -712,8 +723,6 @@ var AuthPrompt = GObject.registerClass({ } this._entryArea.hide(); - if (this._message.text === '') - this._message.hide(); this._fadeInElement(this._authList); } -- 2.51.0 From bf8ecd9f1dec3a58c9734ae0b6bfb5ab6f7e0e0d Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 18:48:48 +0100 Subject: [PATCH 19/30] gdm/authList: Use vertical instead of orientation orientation isn't a valid property for St.BoxLayout --- js/gdm/authList.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/gdm/authList.js b/js/gdm/authList.js index 6eb34f6d97..b5072fe945 100644 --- a/js/gdm/authList.js +++ b/js/gdm/authList.js @@ -32,7 +32,7 @@ const ItemIconPopup = class extends PopupMenu.PopupMenu { this.actor.add_style_class_name('login-dialog-item-icon-popup'); const labels = new St.BoxLayout({ - orientation: Clutter.Orientation.VERTICAL, + vertical: true, style_class: 'login-dialog-item-icon-popup-labels', }); labels.add_child(new St.Label({text: title})); @@ -95,7 +95,7 @@ const AuthListItem = GObject.registerClass({ x_expand: true, }); this._labelBox = new St.BoxLayout({ - orientation: Clutter.Orientation.VERTICAL, + vertical: true, y_align: Clutter.ActorAlign.CENTER, x_expand: true, }); @@ -171,7 +171,7 @@ var AuthList = GObject.registerClass({ }, class AuthList extends St.BoxLayout { _init() { super._init({ - orientation: Clutter.Orientation.VERTICAL, + vertical: true, style_class: 'login-dialog-auth-list-layout', y_align: Clutter.ActorAlign.CENTER, x_expand: true, -- 2.51.0 From 2c10304549a203ea1e5fca2ad6e08e0ee5b0f701 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 17:47:17 +0100 Subject: [PATCH 20/30] gdm/authList: Use St.Icon instead of iconName as property --- js/gdm/authList.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/authList.js b/js/gdm/authList.js index b5072fe945..0c8ef1f18d 100644 --- a/js/gdm/authList.js +++ b/js/gdm/authList.js @@ -62,7 +62,7 @@ class ItemIcon extends St.Button { _init(iconName, iconTitle, iconSubtitle) { super._init({ style_class: 'login-dialog-item-icon', - iconName, + child: new St.Icon({icon_name: iconName}), }); this._popup = new ItemIconPopup(this, iconTitle, iconSubtitle); -- 2.51.0 From 480c3f08428161c3f5ef2e85d7ddc7e9a0c42737 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 19:02:04 +0100 Subject: [PATCH 21/30] gdm/loginDialog: Use propper icon name for authMenuButton --- js/gdm/loginDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index f59663401b..ab5b9c3d77 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -445,7 +445,7 @@ var LoginDialog = GObject.registerClass({ _createAuthMenuButton() { this._authMenuButton = new AuthMenuButton.AuthMenuButton({ title: _('Login Options'), - iconName: 'cog-wheel-symbolic', + iconName: 'emblem-system-symbolic', sectionOrder: [_PRIMARY_LOGIN_METHOD_SECTION_NAME, _SESSION_TYPE_SECTION_NAME], }); this._authMenuButton.updateSensitivity(false); -- 2.51.0 From 56de4883ea483307607d148e2880da220cf782c5 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Wed, 1 Apr 2026 13:05:30 +0200 Subject: [PATCH 22/30] gdm/LoginDialog: Reduce min height of authprompt authprompt is smaller so min height has to be smaller --- js/gdm/loginDialog.js | 2 +- js/ui/unlockDialog.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js index ab5b9c3d77..cdf6f23e2d 100644 --- a/js/gdm/loginDialog.js +++ b/js/gdm/loginDialog.js @@ -34,7 +34,7 @@ const UserWidget = imports.ui.userWidget; const _FADE_ANIMATION_TIME = 250; const _SCROLL_ANIMATION_TIME = 500; -const _FIXED_TOP_ACTOR_HEIGHT = 400; +const _FIXED_TOP_ACTOR_HEIGHT = 300; const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0; const _PRIMARY_LOGIN_METHOD_SECTION_NAME = _('Login Options'); const _SESSION_TYPE_SECTION_NAME = _('Session Type'); diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 654959190e..477edbe8fd 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -32,7 +32,7 @@ const BLUR_SIGMA = 60; const SUMMARY_ICON_SIZE = 32; -const FIXED_PROMPT_HEIGHT = 400; +const FIXED_PROMPT_HEIGHT = 300; var NotificationsBox = GObject.registerClass({ Signals: { 'wake-up-screen': {} }, -- 2.51.0 From 074089190aad31dc52f4da9748a2bda7cb04f239 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 12 Dec 2025 16:21:02 +0100 Subject: [PATCH 23/30] gdm/webLogin: Some fixes for backport 1. Use connect with notify::reactive because bind_property_full is not available 2. Use vertical property because orientation isn't available 3. Set '' as the default value for message --- js/gdm/webLogin.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index f4972144fa..d2e947f646 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -144,14 +144,13 @@ var WebLoginDialog = GObject.registerClass({ y_expand: true, visible: false, }); - this.bind_property_full('reactive', - this, 'opacity', - GObject.BindingFlags.SYNC_CREATE, - (_bind, source) => [true, source ? 255 : 128], - null); + this.connect('notify::reactive', () => { + this.opacity = this.reactive ? 255 : 128; + }); + this.opacity = this.reactive ? 255 : 128; this._contentBox = new St.BoxLayout({ - orientation: Clutter.Orientation.VERTICAL, + vertical: true, x_expand: true, y_expand: true, }); @@ -161,7 +160,7 @@ var WebLoginDialog = GObject.registerClass({ this._contentBox.add_child(this._webLoginPrompt); this._buttonBox = new St.BoxLayout({ - orientation: Clutter.Orientation.HORIZONTAL, + vertical: false, x_align: Clutter.ActorAlign.CENTER, x_expand: true, }); @@ -290,7 +289,7 @@ var WebLoginIntro = GObject.registerClass( class WebLoginIntro extends St.Button { _init(params) { const {message} = Params.parse(params, { - message: null, + message: '', }); const label = new St.Label({ -- 2.51.0 From 908cce536d7933bb09138e4022af46813fe82092 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 15 Dec 2025 13:36:31 +0100 Subject: [PATCH 24/30] gdm/webLogin: Vertically center align labels of buttons --- js/gdm/webLogin.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index d2e947f646..062ad5f309 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -205,6 +205,7 @@ var WebLoginDialog = GObject.registerClass({ child: new St.Label({ text: b.label, style_class: 'web-login-button-label', + y_align: Clutter.ActorAlign.CENTER, }), }); @@ -295,6 +296,7 @@ class WebLoginIntro extends St.Button { const label = new St.Label({ text: message, style_class: 'web-login-button-label', + y_align: Clutter.ActorAlign.CENTER, }); super._init({ @@ -304,6 +306,7 @@ class WebLoginIntro extends St.Button { reactive: true, can_focus: true, child: label, + y_align: Clutter.ActorAlign.CENTER, }); } -- 2.51.0 From 0e08e9a99057f24e3f8e57d66115d8368d00f2d0 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Mon, 15 Dec 2025 13:53:08 +0100 Subject: [PATCH 25/30] gdm/webLogin: Set data to qr texture with the right args This old version has a different signature for setting text data. --- js/ui/qrCode.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/js/ui/qrCode.js b/js/ui/qrCode.js index 547ad7d153..adf6e40051 100644 --- a/js/ui/qrCode.js +++ b/js/ui/qrCode.js @@ -87,14 +87,12 @@ var QrCode = GObject.registerClass({ GnomeQR.EccLevel.LOW, cancellable); - const coglContext = global.stage.context.get_backend().get_cogl_context(); const bpp = Cogl.pixel_format_get_bytes_per_pixel(Cogl.PixelFormat.RGBA_8888, 0); const rowStride = qrSize * bpp; const content = St.ImageContent.new_with_preferred_size(qrSize, qrSize); - content.set_bytes( - coglContext, - pixelData, + content.set_data( + pixelData.get_data(), Cogl.PixelFormat.RGBA_8888, qrSize, qrSize, -- 2.51.0 From 97ac6d29ff531f15dcadd907164ae5c4609bb016 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 12:30:43 +0100 Subject: [PATCH 26/30] gdm/webLogin: Make spinner size 16 In old versions spinner icon would be duplicated to fill the space instead of scaled. --- js/gdm/webLogin.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/gdm/webLogin.js b/js/gdm/webLogin.js index 062ad5f309..ac79816699 100644 --- a/js/gdm/webLogin.js +++ b/js/gdm/webLogin.js @@ -12,7 +12,7 @@ const { QrCode } = imports.ui.qrCode; Gio._promisify(GnomeQR, 'generate_qr_code_async', 'generate_qr_code_finish'); const QR_CODE_SIZE = 150; -const WEB_LOGIN_SPINNER_SIZE = 35; +const WEB_LOGIN_SPINNER_SIZE = 16; const URL_LABEL_LONG_THRESHOLD = 45; var WebLoginPrompt = GObject.registerClass( -- 2.51.0 From 36e72660620d28929d250ee958df0eb0834a163d Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 12:31:48 +0100 Subject: [PATCH 27/30] gdm/unlockDialog: Use proper icon for gear In old versions the icon name is called 'emblem-system-symbolic' --- js/ui/unlockDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 477edbe8fd..85b512aa85 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -646,7 +646,7 @@ var UnlockDialog = GObject.registerClass({ // Login Options button this._authMenuButton = new AuthMenuButton.AuthMenuButton({ title: _('Login Options'), - iconName: 'cog-wheel-symbolic', + iconName: 'emblem-system-symbolic', }); this._authMenuButton.connect('active-item-changed', () => { const authMechanism = this._authMenuButton.getActiveItem(); -- 2.51.0 From 39d93c9d86f99e3ed46544d052ceae188e2adc25 Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 27 Mar 2026 17:53:33 +0100 Subject: [PATCH 28/30] gdm/unlockDialog: Use vertical boolean instead orientation --- js/ui/unlockDialog.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js index 85b512aa85..ab4141e2c3 100644 --- a/js/ui/unlockDialog.js +++ b/js/ui/unlockDialog.js @@ -335,7 +335,7 @@ class UnlockDialogClock extends St.BoxLayout { _init() { super._init({ style_class: 'unlock-dialog-clock', - orientation: Clutter.Orientation.VERTICAL, + vertical: true, y_align: Clutter.ActorAlign.CENTER, }); -- 2.51.0 From 0b4f7dcb4ec6821e38888898a8298a1e8a5e88bf Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Thu, 2 Apr 2026 18:55:31 +0200 Subject: [PATCH 29/30] gdm/unlockDialog: Don't use timeout_add_once --- js/gdm/authServicesLegacy.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/gdm/authServicesLegacy.js b/js/gdm/authServicesLegacy.js index 5955aeadff..4c5a49effa 100644 --- a/js/gdm/authServicesLegacy.js +++ b/js/gdm/authServicesLegacy.js @@ -136,12 +136,13 @@ var AuthServicesLegacy = GObject.registerClass({ this._fingerprintReadyTimeoutId !== 0) return; - this._fingerprintReadyTimeoutId = GLib.timeout_add_once( + this._fingerprintReadyTimeoutId = GLib.timeout_add( GLib.PRIORITY_DEFAULT, FINGERPRINT_READY_TIMEOUT_MS, () => { this._fingerprintReadyTimeoutId = 0; this._setFingerprintReady(true); + return GLib.SOURCE_REMOVE; }); } -- 2.51.0 From 17a21d8e27fddb369977c50e9e62de177222120b Mon Sep 17 00:00:00 2001 From: Joan Torres Lopez Date: Fri, 26 Dec 2025 12:34:11 +0100 Subject: [PATCH 30/30] fingerprintManager: Update getDefaultService using remote This is how async methods are called in this version. --- js/misc/fingerprintManager.js | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/js/misc/fingerprintManager.js b/js/misc/fingerprintManager.js index 151e787e0b..4467e0bfa9 100644 --- a/js/misc/fingerprintManager.js +++ b/js/misc/fingerprintManager.js @@ -64,23 +64,23 @@ var FingerprintManager = GObject.registerClass({ } async checkReaderType(cancellable = null) { - try { - // Wrappers don't support null cancellable, so let's ignore it in case - const args = cancellable ? [cancellable] : []; - const [devicePath] = - await this._fingerprintManagerProxy.GetDefaultDeviceAsync(...args); - - const fprintDeviceProxy = this._getFprintDeviceProxy(devicePath); - await fprintDeviceProxy.init_async(GLib.PRIORITY_DEFAULT, cancellable ?? null); - - const fingerprintReaderKey = fprintDeviceProxy['scan-type'].toUpperCase(); - const fingerprintReaderType = FingerprintReaderType[fingerprintReaderKey]; - this._setFingerprintReaderType(fingerprintReaderType); - } catch (e) { - if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) + this._fingerprintManagerProxy.GetDefaultDeviceRemote((result, error) => { + if (error) { + this._handleFingerprintError(error); return; - this._handleFingerprintError(e); - } + } + + try { + const [devicePath] = result; + const fprintDeviceProxy = this._getFprintDeviceProxy(devicePath); + fprintDeviceProxy.init(cancellable ?? null); + const fingerprintReaderKey = fprintDeviceProxy['scan-type'].toUpperCase(); + const fingerprintReaderType = FingerprintReaderType[fingerprintReaderKey]; + this._setFingerprintReaderType(fingerprintReaderType); + } catch (e) { + this._handleFingerprintError(e); + } + }); } async _initFingerprintManagerProxy() { -- 2.51.0