サーバーサイド装飾コンポジター

Server Side Decoration Compositor は、xdg-shell でのサーバーサイドのウィンドウ装飾を示す簡単な例です。

はじめに

Server Side Decoration Compositor はサーバーサイドのウィンドウ装飾を実装したデスクトップスタイルの Wayland コンポジターの例です。

Qtを使った Qt Wayland Compositorを Qt で作成する基本な原理についてはMinimal QML example を参照してください。

装飾

ウィンドウ装飾とは、ウィンドウシステムのほとんどのウィンドウに付随する追加のUIを指します。例えば、以下のようなものがあります:

  • ウィンドウの表面を囲むグラフィカルな枠。ユーザーがクリックしてドラッグすることで、ウィンドウのサイズを変更することができます。
  • ウィンドウのタイトルバー。ウィンドウを移動するために使われる。
  • ウィンドウを最大化、最小化、閉じるためのシステム・ツール・ボタン。

伝統的にWaylandでは、これらの装飾をレンダリングするのはクライアントの仕事でした。同時に、ウィンドウの位置、サイズ、状態はコンポジターの領域です。いくつかのシェル拡張はオプションでサーバーサイドの装飾をサポートします。これにより、コンポジターはクライアントにウィンドウの装飾を描画すべきではないことを伝えることができます。代わりに、コンポジターがウィンドウ装飾の描画を担当する。これは、macOS、Windows、X11などの他のウィンドウシステムで装飾がどのように処理されるかに対応しています。ある種のクライアントはこれをまったくサポートしていない可能性があることは注目に値する。システムがそのようなアプリケーションを実行することを想定している場合は、この点も考慮する必要があります。

サーバーサイドの装飾の利点:

  • クライアントはWaylandバッファにシステムUI用のスペースを確保する必要がありません。
  • Qt Quick またOpenGLベースのクライアントは別のFBOにレンダリングし、コンテンツをWaylandバッファにコピーする必要がありません。
  • クライアントのウィンドウは、どのUIツールキットが使用されているかに関係なく、一貫した外観を持ちます。
  • リサイズ、クローズ、ウィンドウの状態変更などのシステム機能は、サーバとクライアントで共有するのではなく、サーバに一元化されます。

コード

サンプルのコンポジターはXdgShell 拡張機能のみをサポートしています。通常の方法で拡張機能を初期化し、後でアクセスできるようにListModel にサーフェスを追加します。

XdgShell {
    onToplevelCreated: (toplevel, xdgSurface) => shellSurfaces.append({shellSurface: xdgSurface});
}
XdgDecorationManagerV1 {
    preferredMode: XdgToplevel.ServerSideDecoration
}

さらに、XdgDecorationManagerV1 拡張機能を初期化しています。これにより、サーバーサイドの装飾を好むことをクライアントに伝えることができます。

このインターフェイスはオプションであるため、クライアントがこのインターフェイスをサポートせず、常に独自の装飾を描画する可能性があります。したがって、このモードはあくまで「優先」であり、トップレベルウィンドウを装飾する前に実際のモードをチェックする必要がある。

Column {
    id: chrome
    width: shellSurfaceItem.implicitWidth
    Rectangle {
        visible: modelData.toplevel.decorationMode === XdgToplevel.ServerSideDecoration
        width: parent.width
        height: 30
        gradient: "HeavyRain";
        Text {
            text: modelData.toplevel.title
            anchors.centerIn: parent
        }
        Item {
            anchors.right: parent.right
            width: 30
            height: 30
            Text { text: "X"; anchors.centerIn: parent }
            TapHandler {
                onTapped: modelData.toplevel.sendClose()
            }
        }
        DragHandler {
            target: chrome
        }
    }
    ShellSurfaceItem {
        id: shellSurfaceItem
        moveItem: parent
        shellSurface: modelData
        onSurfaceDestroyed: shellSurfaces.remove(index)
    }
}

各ウィンドウに対して、その上にシンプルなタイトルバーを作成する。タイトルバーには、グラデーション、テキスト、位置を管理するDragHandler 、閉じるボタンがあります。

画像は、左上に装飾マネージャの拡張機能をサポートしたクライアント、右下にクライアントサイドの装飾を施した同じクライアントを示しています。

プロジェクト例 @ 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.