Compositeur fantaisie
Fancy Compositor est un exemple qui montre comment écrire un compositeur Wayland fantaisiste en pur QML.
Introduction
Fancy Compositor est un petit exemple de compositeur Wayland de style bureautique qui démontre la puissance et la facilité des Qt Wayland Compositor QML.
L'exemple Fancy Compositor est similaire à l'exemple Minimal QML, dans la mesure où il s'agit d'un compositeur Wayland à part entière, implémenté uniquement à l'aide de code QML.
Initialisation du compositeur
Comme dans l'exemple Minimal QML, Fancy Compositor prend en charge les principales extensions du shell qui sont prises en charge par Qt.
// Shell surface extension. Needed to provide a window concept for Wayland clients. // I.e. requests and events for maximization, minimization, resizing, closing etc. XdgShell { onToplevelCreated: (toplevel, xdgSurface) => screen.handleShellSurface(xdgSurface) } // Minimalistic shell extension. Mainly used for embedded applications. IviApplication { onIviSurfaceCreated: (iviSurface) => screen.handleShellSurface(iviSurface) } // Deprecated shell extension, still used by some clients WlShell { onWlShellSurfaceCreated: (shellSurface) => screen.handleShellSurface(shellSurface) }
Celles-ci sont instanciées en tant qu'enfants du site WaylandCompositor, qui les ajoute automatiquement à la liste des interfaces prises en charge, laquelle est diffusée aux clients par le serveur.
Lorsqu'un client connecté crée une surface et la lie à l'une des extensions shell, le signal correspondant est émis. Il appelle alors une méthode dans notre classe personnalisée WaylandOutput, qui ajoute le ShellSurface à un ListModel.
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
Ce modèle est utilisé comme source pour une Repeater qui crée ShellSurfaceItems à l'intérieur de la WaylandOutput du compositeur. Cela ajoute une vue de la surface dans la scène Qt Quick. Comme il s'agit d'un ShellSurfaceItem, il dispose également de certaines options d'interaction pour l'utilisateur du compositeur, en fonction de l'extension shell utilisée.
Repeater { model: output.shellSurfaces // Chrome displays a shell surface on the screen (See Chrome.qml) Chrome { shellSurface: modelData onDestroyAnimationFinished: output.shellSurfaces.remove(index) } }
Clavier
En plus des fonctions de base du système de fenêtrage, le Fancy Compositor prend également en charge un clavier à l'écran optionnel fonctionnant en cours de processus. Ce clavier utilise le module Qt Virtual Keyboard et sera activé si le module est disponible.
import QtQuick import QtQuick.VirtualKeyboard InputPanel { visible: active y: active ? parent.height - height : parent.height anchors.left: parent.left anchors.right: parent.right }
Le code est simple. Nous instancions un InputPanel dans la partie inférieure de la sortie, et nous nous assurons qu'il est visible si et seulement s'il est actuellement actif.
Loader { anchors.fill: parent source: "Keyboard.qml" }
Le clavier est ensuite ajouté à l'élément WaylandOutput à l'aide d'un élément Loader. Le Loader est utilisé ici pour éviter d'avoir une dépendance dure sur le module Qt Virtual Keyboard . Si le chargement échoue, le compositeur continuera à fonctionner normalement, mais sans prendre en charge le clavier à l'écran.
Enfin, nous avons besoin d'un moyen pour le compositeur de communiquer la saisie de texte à ses clients. Cela se fait par l'intermédiaire d'une extension text-input. L'exemple Fancy Compositor prend en charge le protocole text_input_unstable_v2 ainsi que le protocole qt_text_input_method_unstable_v1 de Qt.
L'extension qt_text_input_method_unstable_v1 est ajoutée au compositeur en instanciant QtTextInputMethodManager comme enfant de WaylandCompositor, et TextInputManager ajoute text_input_unstable_v2.
Les applications Qt les plus récentes choisissent qt_text_input_method_unstable_v1 lorsqu'il est disponible, tandis que les autres clients peuvent utiliser text_input_unstable_v2.
Transitions
Outre les fonctionnalités de base, l'exemple du compositeur fantaisie présente également des transitions animées entre les états.
La première de ces transitions est la transition d'activation. Elle n'est prise en charge que sur XdgShell, car il s'agit de la seule extension de shell qui dispose d'un état activated.
Connections { target: shellSurface.toplevel !== undefined ? shellSurface.toplevel : null // some signals are not available on wl_shell, so let's ignore them ignoreUnknownSignals: true function onActivatedChanged() { // xdg_shell only if (shellSurface.toplevel.activated) { receivedFocusAnimation.start(); } } } SequentialAnimation { id: receivedFocusAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1.02; duration: 100; easing.type: Easing.OutQuad } } ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } NumberAnimation { target: scaleTransform; property: "xScale"; to: 1; duration: 100; easing.type: Easing.InOutQuad } } }
Lorsqu'une fenêtre client est activée dans le cadre du protocole XdgShell, nous déclenchons une animation qui fait apparaître la fenêtre pendant 200 ms.
Le Fancy Compositor prend également en charge une animation de destruction. Celle-ci se déclenche chaque fois que la fenêtre se ferme et que la surface est détruite, que ce soit parce que le client a fermé sa fenêtre de manière élégante ou même s'il s'est arrêté.
onSurfaceDestroyed: { bufferLocked = true; destroyAnimation.start(); } SequentialAnimation { id: destroyAnimation ParallelAnimation { NumberAnimation { target: scaleTransform; property: "yScale"; to: 2/height; duration: 150 } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0.4; duration: 150 } NumberAnimation { target: chrome; property: "opacity"; to: chrome.isChild ? 0 : 1; duration: 150 } } NumberAnimation { target: scaleTransform; property: "xScale"; to: 0; duration: 150 } ScriptAction { script: destroyAnimationFinished() } }
Pour s'assurer que le contenu existe pendant toute la durée de l'animation, nous commençons par verrouiller la mémoire tampon. Cela signifie que l'image finale rendue par le client restera en mémoire jusqu'à ce que nous en ayons terminé avec elle.
Une fois de plus, nous déclenchons une animation à l'échelle de l'objet. L'animation en question imite la mise hors tension d'un écran CRT, donnant un indice visuel à l'utilisateur que la fenêtre se ferme et qu'elle ne s'est pas simplement volatilisée.
N'importe quel type d'effet animé peut être utilisé pour des changements d'état tels que ceux-ci, avec toute la gamme de Qt Quick à votre disposition.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.