Build a Notification Center in Quickshell (2027 Edition)

Cette vidéo est un tutoriel complet pour construire un système de notifications complet (démon, popups et centre d’historique) avec QuickShell sur NixOS, en utilisant QML et JavaScript.

Voir la source

SYNTHÈSE STRUCTURÉE

Installation et configuration initiale de QuickShell

L’intervenant utilise NixOS avec QuickShell version 0.3.0 déjà disponible dans les paquets Nix. Il vérifie la présence du paquet dans sa configuration système, puis lance nixos-rebuild switch pour l’installer. La vérification se fait avec qs --version. Pour les autres distributions (Arch, Debian), il renvoie vers la documentation officielle sur quickshell.org. Le répertoire de travail est ~/.config/quickshell/, créé avec mkdir -p ~/.config/quickshell.

Fichier de configuration partagé (config.js)

Un fichier JavaScript config.js est créé pour centraliser les couleurs (Tokyo Night), la police (JetBrains Mono Nerd Font, taille 16), la hauteur de la barre (30) et un timeout global de 5000 ms pour les notifications. Ce fichier est importé dans les autres fichiers QML via import "config.js" as Config. L’intervenant précise : « Every file today that does import config.js is going to read these colors. »

Structure du fichier notifications.qml

Le fichier principal contient trois éléments dans un Scope (conteneur non visuel de QuickShell) :

  • Un NotificationServer (le démon)
  • Un PanelWindow pour les popups
  • Un second PanelWindow pour le centre de notifications

L’intervenant explique que le NotificationServer implémente la spécification freedesktop.org pour les notifications.

Configuration du NotificationServer

Le serveur est configuré avec trois attributs essentiels :

NotificationServer {
    id: server
    actionsSupported: true
    bodySupported: true
    imageSupported: true
}

Le gestionnaire onNotification active le suivi des notifications : server.tracked = true. L’intervenant précise que « QML takes any signal and autocreates a handler for it by capitalizing the name and prefixing on in front of it ».

Gestion des fenêtres popup

Le PanelWindow utilise exclusionMode: ExclusionMode.Ignore pour ne pas réserver d’espace sur le bureau. Les ancres sont positionnées en haut à droite avec des marges de 12 pixels. La largeur implicite est de 380 pixels, la hauteur utilise Math.max(1, column.implicitHeight). La couleur de fond est transparente.

Construction de la carte de notification (delegate)

Chaque notification est un Rectangle avec :

  • Rayon de 8 pixels
  • Bordure de 2 pixels (rouge si urgence critique, violet sinon)
  • Hauteur préférée : layout.implicitHeight + 20
  • Couleur de fond issue du fichier config

Le contenu utilise un RowLayout avec une image (36x36, aspectFit), un titre (summary, bold, elide à droite) et un corps (body, wrap mode). L’intervenant précise : « We want to truncate the text here with ellipses here. So QML has a property called elide on text. »

Gestion du timeout et de la fermeture

Un Timer est ajouté à chaque carte :

Timer {
    running: card.modelData.urgency !== NotificationUrgency.Critical
    interval: Config.notificationsTimeout
    onTriggered: card.modelData.dismiss()
}

Les notifications critiques ne se ferment pas automatiquement. La fermeture manuelle se fait via un MouseArea qui appelle card.modelData.dismiss().

Centre de notifications avec historique

Un second PanelWindow est créé pour l’historique, visible uniquement quand root.centerOpen est vrai. Il contient :

  • Un en-tête avec le titre « Notifications » et un bouton « Clear all » (visible si history.count > 0)
  • Une liste des notifications avec horodatage, nom de l’application et bouton de suppression individuelle

L’historique est alimenté dans le gestionnaire onNotification :

history.insert(0, {
    summary: n.summary,
    body: n.body,
    appName: n.appName,
    urgency: n.urgency,
    time: Qt.formatDateTime(new Date(), "hh:mm")
})

Communication IPC pour le contrôle

Un IpcHandler est créé pour permettre le contrôle depuis la ligne de commande ou un raccourci clavier :

IpcHandler {
    target: "notifications"
    functions: [
        IpcFunction { name: "toggle"; resultType: IpcResultType.Void; body: { root.centerOpen = !root.centerOpen; } },
        IpcFunction { name: "show"; resultType: IpcResultType.Void; body: { root.centerOpen = true; } },
        IpcFunction { name: "hide"; resultType: IpcResultType.Void; body: { root.centerOpen = false; } }
    ]
}

L’intervenant utilise ensuite qs-p notifications.qml && qs-p notifications.qml ipc-call notifications toggle pour tester.

Intégration avec le gestionnaire de fenêtres

Le tutoriel se termine par l’intégration dans Hyprland avec un bind super + N pour basculer le centre de notifications. L’intervenant mentionne que les OSD volume et luminosité feront l’objet d’une future vidéo.

CONCEPTS CLÉS

  • QuickShell : Toolkit basé sur QML pour créer des composants de shell de bureau (widgets, écrans de verrouillage, lanceurs, OSD)
  • QML : Langage déclaratif pour interfaces utilisateur, similaire à JavaScript/JSON
  • NotificationServer : Implémentation QuickShell de la spécification freedesktop.org pour les notifications
  • ExclusionMode : Propriété QuickShell qui détermine si une fenêtre réserve de l’espace sur le bureau (Ignore = ne réserve pas)
  • IPC Handler : Mécanisme QuickShell pour exposer des fonctions appelables depuis la ligne de commande ou des raccourcis
  • Delegate : Modèle QML pour générer des éléments à partir d’une liste de données

CONCLUSION

Ce tutoriel montre comment construire un système de notifications complet et moderne avec QuickShell, en seulement 200 lignes de code QML/JavaScript. L’approche modulaire (fichier de configuration centralisé, séparation démon/popup/centre) permet une maintenance aisée et une intégration fluide dans n’importe quel environnement de bureau. La puissance de QuickShell réside dans sa capacité à créer des composants système réactifs et personnalisables, tout en restant léger et performant.

Du même canal

Tout voir