Minimales QML

Minimal QML ist ein einfaches Beispiel, das zeigt, wie man einen Wayland-Compositor in QML schreiben kann.

Minimal QML ist ein Beispiel für einen Wayland-Compositor im Desktop-Stil, der ein vollständiges Qt Wayland Compositor mit so wenig Code wie möglich implementiert. Der Compositor ist mit Qt Quick und QML implementiert.

Das WaylandCompositor-Objekt

Das oberste Element des Compositors ist WaylandCompositor. Es stellt den Wayland-Server selbst dar und verwaltet die Verbindungen zu den Clients, wenn sie eingehen.

Standardmäßig unterstützt der Server das Wayland-Kernprotokoll für die Kommunikation mit Clients. Normalerweise werden Sie jedoch auch eine oder mehrere Erweiterungen des Protokolls unterstützen wollen. Dies gibt dem Client mehr Möglichkeiten, seine Rolle im Windowing-System zu beeinflussen.

Qt unterstützt mehrere Standard- und allgemeine Erweiterungen. Darüber hinaus ist es einfach, benutzerdefinierte Erweiterungen zu erstellen und zu unterstützen, solange die Unterstützung sowohl im Client- als auch im Server-Code hinzugefügt werden kann.

Shell-Erweiterungen

Normalerweise unterstützt ein Compositor mindestens eine Shell-Erweiterung. Erweiterungen werden dem Compositor hinzugefügt, indem sie als direkte Kinder des WaylandCompositor -Objekts instanziiert werden. Sie werden automatisch zu seiner extensions Eigenschaft hinzugefügt und an die Clients weitergegeben, wenn diese eine Verbindung herstellen.

WlShell {
    onWlShellSurfaceCreated: (shellSurface) => shellSurfaces.append({shellSurface: shellSurface});
}
XdgShell {
    onToplevelCreated: (toplevel, xdgSurface) => shellSurfaces.append({shellSurface: xdgSurface});
}
IviApplication {
    onIviSurfaceCreated: (iviSurface) => shellSurfaces.append({shellSurface: iviSurface});
}

Das Minimal-QML-Beispiel unterstützt drei verschiedene Shells: WlShell, XdgShell und IviApplication.

Ein Client kann eine Verbindung zu einer dieser Shells herstellen, die dann als Kanal für die Kommunikation zwischen dem Client und dem Compositor verwendet wird, z. B. für die Erstellung neuer Fenster, das Aushandeln der Größe und so weiter.

Wenn ein Client eine neue Oberfläche erstellt, erhält seine aktive Erweiterung ein entsprechendes Signal. Das Signal enthält ein ShellSurface Argument. Je nachdem, welche Erweiterung das Signal empfangen hat, ist dieses Argument von einer Unterklasse von ShellSurface: WlShellSurface, XdgSurface bzw. IviSurface.

Die ShellSurface kann verwendet werden, um auf Funktionen der Shell-Erweiterung für die spezifische Oberfläche zuzugreifen. Im Minimal-QML-Beispiel wollen wir einfach den Client zu unserer Szene hinzufügen. Um das Vorhandensein des neuen Fensters zu dokumentieren, fügen wir es zur sicheren Aufbewahrung zu einem einfachen ListModel hinzu.

ListModel { id: shellSurfaces }

Erstellen der Szene

Der größte Teil des erforderlichen Compositor-Codes ist bereits fertig. Der letzte Schritt besteht darin, dafür zu sorgen, dass die Anwendungen tatsächlich auf dem Bildschirm sichtbar sind.

Für alle Compositors müssen wir mindestens eine Ausgabe definieren. Dies geschieht durch die Instanziierung eines WaylandOutput -Objekts als direktes Kind des WaylandCompositor. Wenn es nur eine einzige Ausgabe gibt, stellt diese den primären Bildschirm auf dem System dar. (Sie können auch mehrere WaylandOutput Objekte erstellen, um mehrere Bildschirme anzusprechen, wenn diese verfügbar sind. Weitere Einzelheiten hierzu finden Sie im Beispiel Multi Screen ).

WaylandOutput {
    sizeFollowsWindow: true
    window: Window {
        width: 1024
        height: 768
        visible: true

Innerhalb von WaylandOutput erstellen wir ein Fenster, das als Container für unsere Szene dient. In diesem Beispiel geben wir diesem eine Größe. Diese Größe wird verwendet, wenn der Compositor als Anwendung in einem anderen Fenstersystem läuft, das Fenster mit benutzerdefinierter Größe unterstützt. In einem typischen Anwendungsfall auf einem eingebetteten Gerät, bei dem der Compositor der einzige laufende Anzeigeserver ist, wird er wahrscheinlich auf einem Vollbild-Plugin (z. B. eglfs) laufen und die hier eingestellte Größe spielt keine Rolle.

Der letzte Schritt besteht darin, Elemente für jedes der erstellten ShellSurface Objekte zu erstellen. Hierfür können wir die Klasse ShellSurfaceItem verwenden.

Repeater {
    model: shellSurfaces
    // ShellSurfaceItem handles displaying a shell surface.
    // It has implementations for things like interactive
    // resize/move, and forwarding of mouse and keyboard
    // events to the client process.
    ShellSurfaceItem {
        shellSurface: modelData
        onSurfaceDestroyed: shellSurfaces.remove(index)
    }
}

Wir erstellen ein ShellSurfaceItem für jede der Schalenflächen in unserem Modell und weisen sie der Eigenschaft shellSurface zu. Darüber hinaus stellen wir sicher, dass das Modell aktualisiert wird, wenn die Shell-Oberfläche zerstört wird. Dies kann geschehen, wenn ein Client ein Fenster manuell schließt, wenn es beendet wird oder abstürzt.

Dies ist der gesamte Code, der für die Erstellung eines funktionalen Wayland-Compositors mit Qt Quick und QML erforderlich ist. Ein weiteres Beispiel für einen in QML geschriebenen Compositor mit ein paar mehr Funktionen finden Sie im Beispiel Fancy Compositor.

Beispielprojekt @ code.qt.io

© 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.