Skip to content

Session Modes

WARNING

This documentation is for GNOME 45 and later. Please see the Legacy Documentation for previous versions.

Session modes are environment states of GNOME Shell. For example, when a user is logged in and using their desktop the Shell is in the user mode.

Since GNOME 42, extensions have the option of operating in other session modes, such as the unlock-dialog mode when the screen is locked. For more details, see the session-modes documentation.

Example Usage

Here is an example of a metadata.json for an extension that can run in the regular user mode and in the unlock-dialog mode (when the screen is locked).

json
{
    "uuid": "session-modes@gjs.guide",
    "name": "Session Modes Example",
    "description": "This is an example of using session modes in an extension.",
    "shell-version": [ "45" ],
    "session-modes": ["user", "unlock-dialog"],
    "url": "https://gjs.guide/extensions/topics/session-modes"
}

Be aware that when the session mode changes between user and unlock-dialog, GNOME Shell may call disable() and enable() on extensions. Extensions should be prepared to handle disable() being called at any time.

Extensions that continue running on the lock screen may want to disable UI elements when the session is locked, while continuing to operate in the background. Note that GNOME Shell may use custom user modes other than user, so the parent mode must be checked as well.

js
import GLib from 'gi://GLib';
import St from 'gi://St';

import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';


export default class ExampleExtension extends Extension {
    constructor(metadata) {
        super(metadata);

        this._indicator = null;
        this._timeoutId = null;
        this._sessionId = null;
    }

    _addIndicator() {
        if (this._indicator === null) {
            this._indicator = new PanelMenu.Button(0.0, 'Remindicator', false);

            const icon = new St.Icon({
                icon_name: 'preferences-system-time-symbolic',
                style_class: 'system-status-icon',
            });
            this._indicator.add_child(icon);

            Main.panel.addToStatusArea('Remindicator', this._indicator);
        }
    }

    _removeIndicator() {
        if (this._indicator) {
            this._indicator.destroy();
            this._indicator = null;
        }
    }

    // When the session mode changes, we will either add or remove our indicator
    // so it is not visible on the lock screen.
    _onSessionModeChanged(session) {
        if (session.currentMode === 'user' || session.parentMode === 'user')
            this._addIndicator();
        else if (session.currentMode === 'unlock-dialog')
            this._removeIndicator();
    }

    enable() {
        // Ensure we take the correct action for the current session mode
        this._onSessionModeChanged(Main.sessionMode);

        // Watch for changes to the session mode
        this._sessionId = Main.sessionMode.connect('updated',
            this._onSessionModeChanged.bind(this));

        // Show a notification every hour
        this._timeoutId = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT,
            60 * 60, () => {
                Main.notify('Reminder', 'An hour has passed!');

                return GLib.SOURCE_CONTINUE;
            });
    }

    disable() {
        if (this._timeoutId) {
            GLib.Source.remove(this._timeoutId);
            this._timeoutId = null;
        }

        if (this._sessionId) {
            Main.sessionMode.disconnect(this._sessionId);
            this._sessionId = null;
        }

        this._removeIndicator();
    }
}

MIT Licensed | GJS, A GNOME Project