Fancy Compositor
Fancy Compositor ist ein Beispiel, das zeigt, wie man einen ausgefallenen Wayland-Compositor in reinem QML schreiben kann.
Einführung
Fancy Compositor ist ein kleines Wayland-Compositor-Beispiel im Desktop-Stil, das die Leistungsfähigkeit und Einfachheit der Qt Wayland Compositor QML-APIs demonstriert.
Das Fancy Compositor Beispiel ähnelt dem Minimal QML Beispiel, da es ein vollwertiger Wayland Compositor ist, der nur mit QML Code implementiert wurde.
Initialisierung des Compositors
Wie das Minimal-QML-Beispiel unterstützt Fancy Compositor die wichtigsten Shell-Erweiterungen, die von Qt unterstützt werden.
// 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) }
Diese werden als Kinder der WaylandCompositor instanziiert, die sie automatisch zur Liste der unterstützten Schnittstellen hinzufügt, die vom Server an die Clients weitergegeben wird.
Wenn ein verbundener Client eine Oberfläche erstellt und sie an eine der Shell-Erweiterungen bindet, wird das entsprechende Signal ausgegeben. Dieses ruft dann eine Methode innerhalb unserer benutzerdefinierten Klasse WaylandOutput auf, die die ShellSurface an ein ListModel anhängt.
function handleShellSurface(shellSurface) { shellSurfaces.append({shellSurface: shellSurface}); }
Dieses Modell wird als Quelle für ein Repeater verwendet, das ShellSurfaceItems innerhalb des WaylandOutput des Compositors erstellt. Dadurch wird eine Ansicht der Oberfläche in der Qt Quick Szene hinzugefügt. Da es sich um ein ShellSurfaceItem handelt, verfügt es auch über bestimmte Interaktionsmöglichkeiten für den Benutzer des Compositors, je nachdem, welche Shell-Erweiterung verwendet wird.
Repeater { model: output.shellSurfaces // Chrome displays a shell surface on the screen (See Chrome.qml) Chrome { shellSurface: modelData onDestroyAnimationFinished: output.shellSurfaces.remove(index) } }
Tastatur
Zusätzlich zu den grundlegenden Funktionen des Fenstersystems unterstützt der Fancy Compositor auch eine optionale Bildschirmtastatur, die während des Prozesses läuft. Diese verwendet das Qt Virtual Keyboard Modul und wird aktiviert, wenn das Modul verfügbar ist.
import QtQuick import QtQuick.VirtualKeyboard InputPanel { visible: active y: active ? parent.height - height : parent.height anchors.left: parent.left anchors.right: parent.right }
Der Code ist einfach. Wir instanziieren ein InputPanel im unteren Teil der Ausgabe und stellen sicher, dass es nur dann sichtbar ist, wenn es gerade aktiv ist.
Loader { anchors.fill: parent source: "Keyboard.qml" }
Die Tastatur wird dann mit Hilfe eines Loader -Elements zu WaylandOutput hinzugefügt. Das Loader wird hier verwendet, um eine harte Abhängigkeit vom Qt Virtual Keyboard Modul zu vermeiden. Wenn das Laden fehlschlägt, arbeitet der Compositor normal weiter, aber ohne Unterstützung für eine Bildschirmtastatur.
Schließlich benötigen wir eine Möglichkeit für den Compositor, die Texteingabe an seine Clients zu übermitteln. Dies geschieht über eine text-input
-Erweiterung. Das Fancy Compositor Beispiel unterstützt sowohl das text_input_unstable_v2
Protokoll als auch das qt_text_input_method_unstable_v1
Protokoll von Qt.
Die Erweiterung qt_text_input_method_unstable_v1
wird dem Compositor hinzugefügt, indem QtTextInputMethodManager als Kind von WaylandCompositor instanziiert wird, und TextInputManager fügt text_input_unstable_v2
hinzu.
Neuere Qt-Anwendungen wählen qt_text_input_method_unstable_v1
, wenn es verfügbar ist, während andere Clients text_input_unstable_v2
verwenden können.
Übergänge
Zusätzlich zu den grundlegenden Funktionen demonstriert das Fancy Compositor-Beispiel auch animierte Übergänge zwischen Zuständen.
Der erste dieser Übergänge ist der Aktivierungsübergang. Dieser wird nur auf XdgShell unterstützt, da dies die einzige Shell-Erweiterung ist, die einen activated Status hat.
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 } } }
Wenn ein Client-Fenster unter dem XdgShell Protokoll aktiviert wird, lösen wir eine Animation aus, die das Fenster für 200 ms "herausspringen" lässt.
Der Fancy Compositor unterstützt auch eine Zerstörungsanimation. Diese wird immer dann ausgelöst, wenn das Fenster geschlossen und die Oberfläche zerstört wird, sei es, weil der Client sein Fenster anmutig geschlossen hat, oder auch, wenn er abstürzt.
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() } }
Um sicherzustellen, dass der Inhalt für die Dauer der Animation vorhanden ist, wird zunächst der Puffer gesperrt. Das bedeutet, dass das letzte vom Client gerenderte Bild im Speicher bleibt, bis wir damit fertig sind.
Auch hier lösen wir eine Animation auf der Skala des Elements aus. Die Animation imitiert das Ausschalten eines CRT-Bildschirms und gibt dem Benutzer einen visuellen Hinweis darauf, dass das Fenster geschlossen wird und sich nicht einfach in Luft auflöst.
Jede Art von animiertem Effekt kann für solche Zustandsänderungen verwendet werden, wobei die gesamte Palette von Qt Quick zur Verfügung steht.
© 2025 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.