From 45a2b77867f29804e11e46b9f09dc9a0ff10c14a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Fri, 12 Dec 2025 02:29:35 +0100 Subject: [PATCH 1/4] dbus-interfaces: Update MalcontentTimer child interface Update org.freedesktop.MalcontentTimer1.Child interface to include the new screen time extensions functionality. The interface has been updated from https://gitlab.freedesktop.org/pwithnall/malcontent/-/blob/main/libmalcontent-timer/org.freedesktop.MalcontentTimer1.Child.xml, and it has not been modified after being copied. Part-of: --- ...org.freedesktop.MalcontentTimer1.Child.xml | 90 ++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/data/dbus-interfaces/org.freedesktop.MalcontentTimer1.Child.xml b/data/dbus-interfaces/org.freedesktop.MalcontentTimer1.Child.xml index ee5e714ba6..649aa020fc 100644 --- a/data/dbus-interfaces/org.freedesktop.MalcontentTimer1.Child.xml +++ b/data/dbus-interfaces/org.freedesktop.MalcontentTimer1.Child.xml @@ -31,8 +31,9 @@ The `MalcontentTimer1.Child` interface allows a trusted component in a child user account’s session to record screen time and app usage periods - for that account. Such a component might be the shell process of the - session, for example. + for that account, to query the time remaining before the limit is reached, + and to request extensions to the screen time limits. Such a component + might be the shell process of the session, for example. Data is recorded as tuples of (start time, end time, record type, identifier), where the record type is @@ -123,5 +124,90 @@ stateless. --> + + + + + + + + + + + + + + + + + -- GitLab From 572122f524693b846e1f9f2264ffad24f5479d91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Sat, 3 Jan 2026 16:17:45 +0100 Subject: [PATCH 2/4] polkitAgent: Allow malcontent action when locked Allow org.freedesktop.Malcontent.SessionLimits.Extend action id when screen is locked, so it's possible to show polkit authentication dialogs on lock screen for parental controls session limits integration in the future. Part-of: --- js/ui/components/polkitAgent.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/js/ui/components/polkitAgent.js b/js/ui/components/polkitAgent.js index 119f2da66f..c1566c2631 100644 --- a/js/ui/components/polkitAgent.js +++ b/js/ui/components/polkitAgent.js @@ -439,8 +439,10 @@ class AuthenticationAgent extends Shell.PolkitAuthenticationAgent { } _onInitiate(nativeAgent, actionId, message, iconName, cookie, userNames) { - // Don't pop up a dialog while locked - if (Main.sessionMode.isLocked) { + // Don't pop up a dialog while locked, unless it's triggered by user + // action from the lock screen, such as extending the session limits + if (Main.sessionMode.isLocked && + actionId !== 'org.freedesktop.Malcontent.SessionLimits.Extend') { Main.sessionMode.connectObject('updated', () => { Main.sessionMode.disconnectObject(this); -- GitLab From 40745e5cf07639816b07ee167edab712b5b1ef61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Fri, 12 Dec 2025 02:32:45 +0100 Subject: [PATCH 3/4] authPrompt: Implement screen time ignore button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implement screen time ignore button which allows the parent to extend the child’s computer time for the rest of the day. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/-/work_items/8578 Part-of: --- .../gnome-shell-sass/widgets/_login-lock.scss | 10 +++ js/gdm/authPrompt.js | 63 +++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/data/theme/gnome-shell-sass/widgets/_login-lock.scss b/data/theme/gnome-shell-sass/widgets/_login-lock.scss index d11d7224bc..5929ccc572 100644 --- a/data/theme/gnome-shell-sass/widgets/_login-lock.scss +++ b/data/theme/gnome-shell-sass/widgets/_login-lock.scss @@ -271,6 +271,16 @@ $_gdm_dialog_width: 25em; .parental-controls-shield-description { text-align: center; } + + .parental-controls-shield-button { + margin-top: 0.85em; + @extend %lockscreen_button; + @extend %title_4; + padding: $base_margin * 4 $base_margin * 11; + color: $_gdm_fg; + background-color: transparentize($_gdm_fg, .9); + border-radius: $forced_circular_radius; + } } // Notifications diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index 4a9e4f67b3..1486a97fca 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -1,4 +1,5 @@ import Clutter from 'gi://Clutter'; +import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import Atk from 'gi://Atk'; import GObject from 'gi://GObject'; @@ -15,6 +16,11 @@ import * as ShellEntry from '../ui/shellEntry.js'; import * as UserWidget from '../ui/userWidget.js'; import {wiggle} from '../misc/animationUtils.js'; +import {loadInterfaceXML} from '../misc/fileUtils.js'; + +const TimerChildIface = loadInterfaceXML('org.freedesktop.MalcontentTimer1.Child'); +const TimerChildProxy = Gio.DBusProxy.makeProxyWrapper(TimerChildIface); + const DEFAULT_BUTTON_WELL_ICON_SIZE = 16; const DEFAULT_BUTTON_WELL_ANIMATION_DELAY = 1000; @@ -29,6 +35,24 @@ class ParentalControlsShield extends St.BoxLayout { x_align: Clutter.ActorAlign.CENTER, }); + this._requestExtensionCookie = null; + + this._timerChildProxy = TimerChildProxy(Gio.DBus.system, + 'org.freedesktop.MalcontentTimer1', + '/org/freedesktop/MalcontentTimer1', + (proxy, error) => { + if (error) + console.error(`Failed to get TimerChild proxy: ${error}`); + }, + null, /* cancellable */ + Gio.DBusProxyFlags.DO_NOT_AUTO_START_AT_CONSTRUCTION + ); + + this._timerChildProxy.connectSignal('ExtensionResponse', (proxy, sender, params) => + this._onExtensionResponse(proxy, sender, params)); + + this.connect('destroy', this._onDestroy.bind(this)); + this._titleLabel = new St.Label({ style_class: 'parental-controls-shield-title', text: _('Screen Time Limit Reached'), @@ -41,6 +65,45 @@ class ParentalControlsShield extends St.BoxLayout { }); this._descriptionLabel.clutter_text.line_wrap = true; this.add_child(this._descriptionLabel); + + this._ignoreButton = new St.Button({ + style_class: 'parental-controls-shield-button', + // Translators: this is for ignoring a screen time limit for parental controls + label: _('Ignore'), + x_align: Clutter.ActorAlign.CENTER, + }); + this._ignoreButton.connect('clicked', + () => this._onIgnoreButtonClicked().catch(logError)); + this.add_child(this._ignoreButton); + } + + _onDestroy() { + this._requestExtensionCookie = null; + } + + async _onIgnoreButtonClicked() { + if (this._requestExtensionCookie) + return; + + try { + [this._requestExtensionCookie] = await this._timerChildProxy.RequestExtensionAsync( + 'login-session', + '', + 0, + {}, + Gio.DBusCallFlags.ALLOW_INTERACTIVE_AUTHORIZATION + ); + } catch (e) { + console.warn(`Failed to obtain screen time extension: ${e.message}`); + } + } + + _onExtensionResponse(proxy, sender, [_, cookie]) { + if (this._requestExtensionCookie === null || + cookie !== this._requestExtensionCookie) + return; + + this._requestExtensionCookie = null; } }); -- GitLab From 8aaeec00030de3b9b4feb122c96a8ff75d3828f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacy=20Kuchci=C5=84ski?= Date: Fri, 9 Jan 2026 15:14:23 +0100 Subject: [PATCH 4/4] authPrompt: Focus entry after extending session Re-focus password entry after ignoring screen time limits for the rest of the day. Part-of: --- js/gdm/authPrompt.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index 1486a97fca..1d5a5f26b1 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -807,6 +807,9 @@ export const AuthPrompt = GObject.registerClass({ this.replace_child(this._mainContent, newMainContent); this._mainContent = newMainContent; } + + if (this._mainContent === this._inputWell) + this._entry.grab_key_focus(); } begin(params) { -- GitLab